]> git.lizzy.rs Git - rust.git/blobdiff - src/items.rs
Merge pull request #2138 from topecongiro/comments-around-trait-bounds
[rust.git] / src / items.rs
index e936999ac7d18373c7c431a617df2e451cf29e9d..dcca3a77cac0f2bda9cb37449f57cd9f17dd28e8 100644 (file)
@@ -14,7 +14,7 @@
 use std::cmp::min;
 
 use syntax::{abi, ast, ptr, symbol};
-use syntax::ast::ImplItem;
+use syntax::ast::{CrateSugar, ImplItem};
 use syntax::codemap::{BytePos, Span};
 use syntax::visit;
 
@@ -33,8 +33,8 @@
 use utils::{colon_spaces, contains_skip, end_typaram, first_line_width, format_abi,
             format_constness, format_defaultness, format_mutability, format_unsafety,
             format_visibility, is_attributes_extendable, last_line_contains_single_line_comment,
-            last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, stmt_expr,
-            trim_newlines, trimmed_last_line_width};
+            last_line_used_width, last_line_width, mk_sp, semicolon_for_expr, starts_with_newline,
+            stmt_expr, trim_newlines, trimmed_last_line_width};
 use vertical::rewrite_with_alignment;
 use visitor::FmtVisitor;
 
@@ -62,11 +62,11 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
             return None;
         }
 
-        let attrs_str = try_opt!(self.attrs.rewrite(context, shape));
+        let attrs_str = self.attrs.rewrite(context, shape)?;
         let mut result = if attrs_str.is_empty() {
             "let ".to_owned()
         } else {
-            try_opt!(combine_strs_with_missing_comments(
+            combine_strs_with_missing_comments(
                 context,
                 &attrs_str,
                 "let ",
@@ -76,14 +76,14 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 ),
                 shape,
                 false,
-            ))
+            )?
         };
 
         // 4 = "let ".len()
-        let pat_shape = try_opt!(shape.offset_left(4));
+        let pat_shape = shape.offset_left(4)?;
         // 1 = ;
-        let pat_shape = try_opt!(pat_shape.sub_width(1));
-        let pat_str = try_opt!(self.pat.rewrite(context, pat_shape));
+        let pat_shape = pat_shape.sub_width(1)?;
+        let pat_str = self.pat.rewrite(context, pat_shape)?;
         result.push_str(&pat_str);
 
         // String that is placed within the assignment pattern and expression.
@@ -94,8 +94,8 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 let separator = type_annotation_separator(context.config);
                 let indent = shape.indent + last_line_width(&result) + separator.len();
                 // 1 = ;
-                let budget = try_opt!(shape.width.checked_sub(indent.width() + 1));
-                let rewrite = try_opt!(ty.rewrite(context, Shape::legacy(budget, indent)));
+                let budget = shape.width.checked_sub(indent.width() + 1)?;
+                let rewrite = ty.rewrite(context, Shape::legacy(budget, indent))?;
 
                 infix.push_str(separator);
                 infix.push_str(&rewrite);
@@ -112,9 +112,9 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
 
         if let Some(ref ex) = self.init {
             // 1 = trailing semicolon;
-            let nested_shape = try_opt!(shape.sub_width(1));
+            let nested_shape = shape.sub_width(1)?;
 
-            result = try_opt!(rewrite_assign_rhs(context, result, ex, nested_shape));
+            result = rewrite_assign_rhs(context, result, ex, nested_shape)?;
         }
 
         result.push(';');
@@ -184,25 +184,29 @@ pub fn new(
         }
     }
 
-    pub fn from_method_sig(method_sig: &'a ast::MethodSig) -> FnSig {
+    pub fn from_method_sig(
+        method_sig: &'a ast::MethodSig,
+        generics: &'a ast::Generics,
+    ) -> FnSig<'a> {
         FnSig {
             unsafety: method_sig.unsafety,
             constness: method_sig.constness.node,
             defaultness: ast::Defaultness::Final,
             abi: method_sig.abi,
             decl: &*method_sig.decl,
-            generics: &method_sig.generics,
+            generics: generics,
             visibility: ast::Visibility::Inherited,
         }
     }
 
     pub fn from_fn_kind(
         fn_kind: &'a visit::FnKind,
+        generics: &'a ast::Generics,
         decl: &'a ast::FnDecl,
         defualtness: ast::Defaultness,
     ) -> FnSig<'a> {
         match *fn_kind {
-            visit::FnKind::ItemFn(_, generics, unsafety, constness, abi, visibility, _) => FnSig {
+            visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig {
                 decl: decl,
                 generics: generics,
                 abi: abi,
@@ -211,8 +215,8 @@ pub fn from_fn_kind(
                 unsafety: unsafety,
                 visibility: visibility.clone(),
             },
-            visit::FnKind::Method(_, ref method_sig, vis, _) => {
-                let mut fn_sig = FnSig::from_method_sig(method_sig);
+            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 {
                     fn_sig.visibility = vis.clone();
@@ -306,20 +310,13 @@ pub fn rewrite_fn(
         let mut newline_brace =
             newline_for_brace(self.config, &fn_sig.generics.where_clause, has_body);
 
-        let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(
-            &context,
-            indent,
-            ident,
-            fn_sig,
-            span,
-            newline_brace,
-            true,
-        ));
+        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.fn_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;
@@ -345,21 +342,22 @@ pub fn rewrite_required_fn(
         indent: Indent,
         ident: ast::Ident,
         sig: &ast::MethodSig,
+        generics: &ast::Generics,
         span: Span,
     ) -> Option<String> {
         // Drop semicolon or it will be interpreted as comment.
         let span = mk_sp(span.lo(), span.hi() - BytePos(1));
         let context = self.get_context();
 
-        let (mut result, _) = try_opt!(rewrite_fn_base(
+        let (mut result, _) = rewrite_fn_base(
             &context,
             indent,
             ident,
-            &FnSig::from_method_sig(sig),
+            &FnSig::from_method_sig(sig, generics),
             span,
             false,
             false,
-        ));
+        )?;
 
         // Re-attach semicolon
         result.push(';');
@@ -413,6 +411,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,
@@ -430,8 +440,6 @@ pub fn visit_enum(
         let generics_str = format_generics(
             &self.get_context(),
             generics,
-            "{",
-            "{",
             self.config.item_brace_style(),
             enum_def.variants.is_empty(),
             self.block_indent,
@@ -503,7 +511,7 @@ fn format_variant_list(
             config: self.config,
         };
 
-        let list = try_opt!(write_list(&items.collect::<Vec<_>>(), &fmt));
+        let list = write_list(&items.collect::<Vec<_>>(), &fmt)?;
         result.push_str(&list);
         result.push('\n');
         Some(result)
@@ -520,7 +528,7 @@ fn format_variant(&self, field: &ast::Variant) -> Option<String> {
         let context = self.get_context();
         let indent = self.block_indent;
         let shape = self.shape();
-        let attrs_str = try_opt!(field.node.attrs.rewrite(&context, shape));
+        let attrs_str = field.node.attrs.rewrite(&context, shape)?;
         let lo = field
             .node
             .attrs
@@ -531,36 +539,19 @@ fn format_variant(&self, field: &ast::Variant) -> Option<String> {
         let variant_body = match field.node.data {
             ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => {
                 // FIXME: Should limit the width, as we have a trailing comma
-                try_opt!(format_struct(
+                format_struct(
                     &context,
-                    "",
-                    field.node.name,
-                    &ast::Visibility::Inherited,
-                    &field.node.data,
-                    None,
-                    field.span,
+                    &StructParts::from_variant(field),
                     indent,
                     Some(self.config.struct_variant_width()),
-                ))
+                )?
             }
             ast::VariantData::Unit(..) => if let Some(ref expr) = field.node.disr_expr {
-                let one_line_width =
-                    field.node.name.to_string().len() + self.snippet(expr.span).len() + 3;
-                if one_line_width <= shape.width {
-                    format!("{} = {}", field.node.name, self.snippet(expr.span))
-                } else {
-                    format!(
-                        "{}\n{}{}",
-                        field.node.name,
-                        shape
-                            .indent
-                            .block_indent(self.config)
-                            .to_string(self.config),
-                        self.snippet(expr.span)
-                    )
-                }
+                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())
+                field.node.name.to_string()
             },
         };
 
@@ -586,7 +577,7 @@ pub fn format_impl(
 ) -> Option<String> {
     if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node {
         let mut result = String::with_capacity(128);
-        let ref_and_type = try_opt!(format_impl_ref_and_type(context, item, offset));
+        let ref_and_type = format_impl_ref_and_type(context, item, offset)?;
         let indent_str = offset.to_string(context.config);
         let sep = format!("\n{}", &indent_str);
         result.push_str(&ref_and_type);
@@ -597,7 +588,7 @@ pub fn format_impl(
             context.budget(last_line_width(&result))
         };
         let option = WhereClauseOption::snuggled(&ref_and_type);
-        let where_clause_str = try_opt!(rewrite_where_clause(
+        let where_clause_str = rewrite_where_clause(
             context,
             &generics.where_clause,
             context.config.item_brace_style(),
@@ -607,7 +598,8 @@ pub fn format_impl(
             where_span_end,
             self_ty.span.hi(),
             option,
-        ));
+            false,
+        )?;
 
         // If there is no where clause, we may have missing comments between the trait name and
         // the opening brace.
@@ -627,13 +619,7 @@ pub fn format_impl(
             }
         }
 
-        if try_opt!(is_impl_single_line(
-            context,
-            items,
-            &result,
-            &where_clause_str,
-            item,
-        )) {
+        if is_impl_single_line(context, items, &result, &where_clause_str, item)? {
             result.push_str(&where_clause_str);
             if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
                 result.push_str(&format!("{}{{{}}}", &sep, &sep));
@@ -665,7 +651,7 @@ pub fn format_impl(
         result.push('{');
 
         let snippet = context.snippet(item.span);
-        let open_pos = try_opt!(snippet.find_uncommented("{")) + 1;
+        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);
@@ -689,7 +675,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('}');
@@ -708,7 +694,7 @@ fn is_impl_single_line(
     item: &ast::Item,
 ) -> Option<bool> {
     let snippet = context.snippet(item.span);
-    let open_pos = try_opt!(snippet.find_uncommented("{")) + 1;
+    let open_pos = snippet.find_uncommented("{")? + 1;
 
     Some(
         context.config.impl_empty_single_line() && items.is_empty() && !result.contains('\n')
@@ -744,19 +730,14 @@ fn format_impl_ref_and_type(
             Some(ref tr) => tr.path.span.lo(),
             None => self_ty.span.lo(),
         };
-        let shape = try_opt!(generics_shape_from_config(
+        let shape = generics_shape_from_config(
             context.config,
             Shape::indented(offset + last_line_width(&result), context.config),
             0,
-        ));
-        let one_line_budget = try_opt!(shape.width.checked_sub(last_line_width(&result) + 2));
-        let generics_str = try_opt!(rewrite_generics_inner(
-            context,
-            generics,
-            shape,
-            one_line_budget,
-            mk_sp(lo, hi),
-        ));
+        )?;
+        let one_line_budget = shape.width.checked_sub(last_line_width(&result) + 2)?;
+        let generics_str =
+            rewrite_generics_inner(context, generics, shape, one_line_budget, mk_sp(lo, hi))?;
 
         let polarity_str = if polarity == ast::ImplPolarity::Negative {
             "!"
@@ -777,14 +758,9 @@ fn format_impl_ref_and_type(
             ) {
                 result.push_str(&trait_ref_str);
             } else {
-                let generics_str = try_opt!(rewrite_generics_inner(
-                    context,
-                    generics,
-                    shape,
-                    0,
-                    mk_sp(lo, hi),
-                ));
-                result.push_str(&try_opt!(rewrite_trait_ref(
+                let generics_str =
+                    rewrite_generics_inner(context, generics, shape, 0, mk_sp(lo, hi))?;
+                result.push_str(&rewrite_trait_ref(
                     context,
                     trait_ref,
                     offset,
@@ -792,7 +768,7 @@ fn format_impl_ref_and_type(
                     false,
                     polarity_str,
                     result_len,
-                )));
+                )?);
             }
         } else {
             result.push_str(&generics_str);
@@ -839,9 +815,8 @@ fn format_impl_ref_and_type(
             Style::Legacy => new_line_offset + trait_ref_overhead,
             Style::Rfc => new_line_offset,
         };
-        result.push_str(&*try_opt!(
-            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!();
@@ -874,7 +849,7 @@ fn rewrite_trait_ref(
     if !retry {
         let offset = offset.block_indent(context.config);
         let shape = Shape::indented(offset, context.config);
-        let trait_ref_str = try_opt!(trait_ref.rewrite(context, shape));
+        let trait_ref_str = trait_ref.rewrite(context, shape)?;
         Some(format!(
             "{}\n{}{}{}",
             generics_str,
@@ -887,45 +862,67 @@ 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(..) => Some(format_unit_struct(struct_parts)),
+        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)
+        }
     }
 }
 
 pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option<String> {
-    if let ast::ItemKind::Trait(unsafety, ref generics, ref type_param_bounds, ref trait_items) =
+    if let ast::ItemKind::Trait(_, unsafety, ref generics, ref type_param_bounds, ref trait_items) =
         item.node
     {
         let mut result = String::with_capacity(128);
@@ -940,20 +937,25 @@ 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 generics_str = try_opt!(rewrite_generics(
-            context,
-            generics,
-            shape,
-            mk_sp(item.span.lo(), body_lo),
-        ));
+        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);
 
-        let trait_bound_str = try_opt!(rewrite_trait_bounds(
+        // 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,
             Shape::indented(offset, context.config),
-        ));
+        )?;
         // If the trait, generics, and trait bound cannot fit on the same line,
         // put the trait bounds on an indented new line
         if offset.width() + last_line_width(&result) + trait_bound_str.len()
@@ -968,8 +970,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
         let has_body = !trait_items.is_empty();
 
         let where_density = if (context.config.where_density() == Density::Compressed
-            && (!result.contains('\n') || context.config.fn_args_layout() == IndentStyle::Block))
-            || (context.config.fn_args_layout() == IndentStyle::Block && result.is_empty())
+            && (!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'))
         {
@@ -985,7 +987,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
             type_param_bounds[type_param_bounds.len() - 1].span().hi()
         };
         let option = WhereClauseOption::snuggled(&generics_str);
-        let where_clause_str = try_opt!(rewrite_where_clause(
+        let where_clause_str = rewrite_where_clause(
             context,
             &generics.where_clause,
             context.config.item_brace_style(),
@@ -995,7 +997,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
             None,
             pos_before_where,
             option,
-        ));
+            false,
+        )?;
         // If the where clause cannot fit on the same line,
         // put the where clause on a new line
         if !where_clause_str.contains('\n')
@@ -1053,7 +1056,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
         result.push('{');
 
         let snippet = context.snippet(item.span);
-        let open_pos = try_opt!(snippet.find_uncommented("{")) + 1;
+        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);
@@ -1085,40 +1088,36 @@ 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(p: &StructParts) -> String {
+    format!("{};", format_header(p.prefix, p.ident, p.vis))
 }
 
 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 {
-        Some(g) => try_opt!(format_generics(
+    let generics_str = match struct_parts.generics {
+        Some(g) => format_generics(
             context,
             g,
-            "{",
-            "{",
             context.config.item_brace_style(),
             fields.is_empty(),
             offset,
-            mk_sp(span.lo(), body_lo),
+            mk_sp(header_hi, body_lo),
             last_line_width(&result),
-        )),
+        )?,
         None => {
             // 3 = ` {}`, 2 = ` {`.
             let overhead = if fields.is_empty() { 3 } else { 2 };
@@ -1166,13 +1165,13 @@ pub fn format_struct_struct(
     let one_line_budget =
         one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget));
 
-    let items_str = try_opt!(rewrite_with_alignment(
+    let items_str = rewrite_with_alignment(
         fields,
         context,
         Shape::indented(offset, context.config),
         mk_sp(body_lo, span.hi()),
         one_line_budget,
-    ));
+    )?;
 
     if !items_str.contains('\n') && !result.contains('\n') && items_str.len() <= one_line_budget {
         Some(format!("{} {} }}", result, items_str))
@@ -1189,28 +1188,45 @@ pub fn format_struct_struct(
     }
 }
 
-fn format_tuple_struct(
+/// Returns a bytepos that is after that of `(` in `pub(..)`. If the given visibility does not
+/// contain `pub(..)`, then return the `lo` of the `defualt_span`. Yeah, but for what? Well, we need
+/// to bypass the `(` in the visibility when creating a span of tuple's body or fn's args.
+fn get_bytepos_after_visibility(
     context: &RewriteContext,
-    item_name: &str,
-    ident: ast::Ident,
     vis: &ast::Visibility,
+    default_span: Span,
+    terminator: &str,
+) -> BytePos {
+    match *vis {
+        ast::Visibility::Crate(s, CrateSugar::PubCrate) => context
+            .codemap
+            .span_after(mk_sp(s.hi(), default_span.hi()), terminator),
+        ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(),
+        ast::Visibility::Restricted { ref path, .. } => path.span.hi(),
+        _ => default_span.lo(),
+    }
+}
+
+fn format_tuple_struct(
+    context: &RewriteContext,
+    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() {
-        context.codemap.span_after(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()
     };
     let body_hi = if fields.is_empty() {
-        context.codemap.span_after(span, ")")
+        context.codemap.span_after(mk_sp(body_lo, span.hi()), ")")
     } else {
         // This is a dirty hack to work around a missing `)` from the span of the last field.
         let last_arg_span = fields[fields.len() - 1].span;
@@ -1223,17 +1239,17 @@ 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);
             let g_span = mk_sp(span.lo(), body_lo);
-            let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span));
+            let generics_str = rewrite_generics(context, generics, shape, g_span)?;
             result.push_str(&generics_str);
 
             let where_budget = context.budget(last_line_width(&result));
             let option = WhereClauseOption::new(true, false);
-            try_opt!(rewrite_where_clause(
+            rewrite_where_clause(
                 context,
                 &generics.where_clause,
                 context.config.item_brace_style(),
@@ -1243,7 +1259,8 @@ fn format_tuple_struct(
                 None,
                 body_hi,
                 option,
-            ))
+                false,
+            )?
         }
         None => "".to_owned(),
     };
@@ -1258,7 +1275,10 @@ fn format_tuple_struct(
                 .to_string(context.config))
         }
         result.push('(');
-        let snippet = context.snippet(mk_sp(body_lo, context.codemap.span_before(span, ")")));
+        let snippet = context.snippet(mk_sp(
+            body_lo,
+            context.codemap.span_before(mk_sp(body_lo, span.hi()), ")"),
+        ));
         if snippet.is_empty() {
             // `struct S ()`
         } else if snippet.trim_right_matches(&[' ', '\t'][..]).ends_with('\n') {
@@ -1270,17 +1290,10 @@ fn format_tuple_struct(
         }
         result.push(')');
     } else {
-        // 3 = `();`
-        let body = try_opt!(rewrite_call_inner(
-            context,
-            "",
-            &fields.iter().map(|field| field).collect::<Vec<_>>()[..],
-            span,
-            Shape::legacy(context.budget(last_line_width(&result) + 3), offset),
-            context.config.fn_call_width(),
-            false,
-        ));
-        result.push_str(&body);
+        let shape = Shape::indented(offset, context.config);
+        let fields = &fields.iter().map(|field| field).collect::<Vec<_>>()[..];
+        let one_line_width = context.config.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')
@@ -1315,14 +1328,14 @@ pub fn rewrite_type_alias(
     result.push_str(&ident.to_string());
 
     // 2 = `= `
-    let shape = try_opt!(Shape::indented(indent + result.len(), context.config).sub_width(2));
+    let shape = Shape::indented(indent + result.len(), context.config).sub_width(2)?;
     let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo());
-    let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span));
+    let generics_str = rewrite_generics(context, generics, shape, g_span)?;
     result.push_str(&generics_str);
 
     let where_budget = context.budget(last_line_width(&result));
     let option = WhereClauseOption::snuggled(&result);
-    let where_clause_str = try_opt!(rewrite_where_clause(
+    let where_clause_str = rewrite_where_clause(
         context,
         &generics.where_clause,
         context.config.item_brace_style(),
@@ -1332,7 +1345,8 @@ pub fn rewrite_type_alias(
         Some(span.hi()),
         generics.span.hi(),
         option,
-    ));
+        false,
+    )?;
     result.push_str(&where_clause_str);
     if where_clause_str.is_empty() {
         result.push_str(" = ");
@@ -1346,20 +1360,18 @@ pub fn rewrite_type_alias(
     let budget = context.budget(indent.width() + line_width + ";".len());
     let type_indent = indent + line_width;
     // Try to fit the type on the same line
-    let ty_str = try_opt!(
-        ty.rewrite(context, Shape::legacy(budget, type_indent))
-            .or_else(|| {
-                // The line was too short, try to put the type on the next line
-
-                // Remove the space after '='
-                result.pop();
-                let type_indent = indent.block_indent(context.config);
-                result.push('\n');
-                result.push_str(&type_indent.to_string(context.config));
-                let budget = context.budget(type_indent.width() + ";".len());
-                ty.rewrite(context, Shape::legacy(budget, type_indent))
-            })
-    );
+    let ty_str = ty.rewrite(context, Shape::legacy(budget, type_indent))
+        .or_else(|| {
+            // The line was too short, try to put the type on the next line
+
+            // Remove the space after '='
+            result.pop();
+            let type_indent = indent.block_indent(context.config);
+            result.push('\n');
+            result.push_str(&type_indent.to_string(context.config));
+            let budget = context.budget(type_indent.width() + ";".len());
+            ty.rewrite(context, Shape::legacy(budget, type_indent))
+        })?;
     result.push_str(&ty_str);
     result.push_str(";");
     Some(result)
@@ -1392,20 +1404,6 @@ pub fn rewrite_struct_field_prefix(
     })
 }
 
-fn rewrite_struct_field_type(
-    context: &RewriteContext,
-    last_line_width: usize,
-    field: &ast::StructField,
-    spacing: &str,
-    shape: Shape,
-) -> Option<String> {
-    let ty_shape = try_opt!(shape.offset_left(last_line_width + spacing.len()));
-    field
-        .ty
-        .rewrite(context, ty_shape)
-        .map(|ty| format!("{}{}", spacing, ty))
-}
-
 impl Rewrite for ast::StructField {
     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
         rewrite_struct_field(context, self, shape, 0)
@@ -1423,9 +1421,9 @@ pub fn rewrite_struct_field(
     }
 
     let type_annotation_spacing = type_annotation_spacing(context.config);
-    let prefix = try_opt!(rewrite_struct_field_prefix(context, field));
+    let prefix = rewrite_struct_field_prefix(context, field)?;
 
-    let attrs_str = try_opt!(field.attrs.rewrite(context, shape));
+    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));
@@ -1440,14 +1438,14 @@ pub fn rewrite_struct_field(
         ""
     });
     // Try to put everything on a single line.
-    let attr_prefix = try_opt!(combine_strs_with_missing_comments(
+    let attr_prefix = combine_strs_with_missing_comments(
         context,
         &attrs_str,
         &prefix,
         missing_span,
         shape,
         attrs_extendable,
-    ));
+    )?;
     let overhead = last_line_width(&attr_prefix);
     let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0);
     for _ in 0..lhs_offset {
@@ -1457,44 +1455,26 @@ pub fn rewrite_struct_field(
     if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() {
         spacing.push(' ');
     }
-    let ty_rewritten = rewrite_struct_field_type(context, overhead, field, &spacing, shape);
-    if let Some(ref ty) = ty_rewritten {
+    let ty_shape = shape.offset_left(overhead + spacing.len())?;
+    if let Some(ref ty) = field.ty.rewrite(context, ty_shape) {
         if !ty.contains('\n') {
-            return Some(attr_prefix + ty);
+            return Some(attr_prefix + &spacing + ty);
         }
     }
 
     // We must use multiline.
-    let last_line_width = last_line_width(&prefix);
-    let ty_rewritten = rewrite_struct_field_type(context, last_line_width, field, &spacing, shape);
-
-    let type_offset = shape.indent.block_indent(context.config);
-    let rewrite_type_in_next_line = || {
-        field
-            .ty
-            .rewrite(context, Shape::indented(type_offset, context.config))
-    };
+    let new_shape = shape.with_max_width(context.config);
+    let ty_rewritten = field.ty.rewrite(context, new_shape)?;
 
-    let field_str = match ty_rewritten {
-        // If we start from the next line and type fits in a single line, then do so.
-        Some(ref ty) => match rewrite_type_in_next_line() {
-            Some(ref new_ty) if !new_ty.contains('\n') => format!(
-                "{}\n{}{}",
-                prefix,
-                type_offset.to_string(context.config),
-                &new_ty
-            ),
-            _ => prefix + ty,
-        },
-        _ => {
-            let ty = try_opt!(rewrite_type_in_next_line());
-            format!(
-                "{}\n{}{}",
-                prefix,
-                type_offset.to_string(context.config),
-                &ty
-            )
-        }
+    let field_str = if prefix.is_empty() {
+        ty_rewritten
+    } else if prefix.len() + first_line_width(&ty_rewritten) + 1 <= shape.width {
+        prefix + " " + &ty_rewritten
+    } 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
     };
     combine_strs_with_missing_comments(
         context,
@@ -1506,16 +1486,73 @@ pub fn rewrite_struct_field(
     )
 }
 
-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>>,
     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),
+            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(),
+            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),
+            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(),
@@ -1523,21 +1560,18 @@ pub fn rewrite_static(
     );
     let prefix = format!(
         "{}{} {}{}{}",
-        format_visibility(vis),
-        prefix,
-        format_mutability(mutability),
-        ident,
+        format_visibility(static_parts.vis),
+        static_parts.prefix,
+        format_mutability(static_parts.mutability),
+        static_parts.ident,
         colon,
     );
     // 2 = " =".len()
-    let ty_str = try_opt!(ty.rewrite(
-        context,
-        try_opt!(
-            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);
@@ -1546,7 +1580,9 @@ pub fn rewrite_static(
             lhs,
             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))
@@ -1564,14 +1600,12 @@ pub fn rewrite_associated_type(
 
     let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt {
         // 2 = ": ".len()
-        let shape = try_opt!(Shape::indented(indent, context.config).offset_left(prefix.len() + 2));
+        let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?;
         let bounds: &[_] = ty_param_bounds;
-        let bound_str = try_opt!(
-            bounds
-                .iter()
-                .map(|ty_bound| ty_bound.rewrite(context, shape))
-                .collect::<Option<Vec<_>>>()
-        );
+        let bound_str = bounds
+            .iter()
+            .map(|ty_bound| ty_bound.rewrite(context, shape))
+            .collect::<Option<Vec<_>>>()?;
         if !bounds.is_empty() {
             format!(": {}", join_bounds(context, shape, &bound_str))
         } else {
@@ -1582,13 +1616,13 @@ pub fn rewrite_associated_type(
     };
 
     if let Some(ty) = ty_opt {
-        let ty_str = try_opt!(ty.rewrite(
+        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))
     } else {
         Some(format!("{}{};", prefix, type_bounds_str))
@@ -1603,13 +1637,7 @@ pub fn rewrite_associated_impl_type(
     context: &RewriteContext,
     indent: Indent,
 ) -> Option<String> {
-    let result = try_opt!(rewrite_associated_type(
-        ident,
-        ty_opt,
-        ty_param_bounds_opt,
-        context,
-        indent,
-    ));
+    let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?;
 
     match defaultness {
         ast::Defaultness::Default => Some(format!("default {}", result)),
@@ -1622,7 +1650,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
         match *self {
             ast::FunctionRetTy::Default(_) => Some(String::new()),
             ast::FunctionRetTy::Ty(ref ty) => {
-                let inner_width = try_opt!(shape.width.checked_sub(3));
+                let inner_width = shape.width.checked_sub(3)?;
                 ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3))
                     .map(|r| format!("-> {}", r))
             }
@@ -1643,10 +1671,8 @@ fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool {
 impl Rewrite for ast::Arg {
     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
         if is_named_arg(self) {
-            let mut result = try_opt!(
-                self.pat
-                    .rewrite(context, Shape::legacy(shape.width, shape.indent))
-            );
+            let mut result = self.pat
+                .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
 
             if !is_empty_infer(context, &*self.ty) {
                 if context.config.space_before_type_annotation() {
@@ -1657,11 +1683,9 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                     result.push_str(" ");
                 }
                 let overhead = last_line_width(&result);
-                let max_width = try_opt!(shape.width.checked_sub(overhead));
-                let ty_str = try_opt!(
-                    self.ty
-                        .rewrite(context, Shape::legacy(max_width, shape.indent))
-                );
+                let max_width = shape.width.checked_sub(overhead)?;
+                let ty_str = self.ty
+                    .rewrite(context, Shape::legacy(max_width, shape.indent))?;
                 result.push_str(&ty_str);
             }
 
@@ -1682,10 +1706,10 @@ fn rewrite_explicit_self(
             let mut_str = format_mutability(m);
             match lt {
                 Some(ref l) => {
-                    let lifetime_str = try_opt!(l.rewrite(
+                    let lifetime_str = l.rewrite(
                         context,
                         Shape::legacy(context.config.max_width(), Indent::empty()),
-                    ));
+                    )?;
                     Some(format!("&{} {}self", lifetime_str, mut_str))
                 }
                 None => Some(format!("&{}self", mut_str)),
@@ -1695,10 +1719,10 @@ fn rewrite_explicit_self(
             assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
 
             let mutability = explicit_self_mutability(&args[0]);
-            let type_str = try_opt!(ty.rewrite(
+            let type_str = ty.rewrite(
                 context,
                 Shape::legacy(context.config.max_width(), Indent::empty()),
-            ));
+            )?;
 
             Some(format!(
                 "{}self: {}",
@@ -1788,7 +1812,7 @@ fn rewrite_fn_base(
     };
     let fd = fn_sig.decl;
     let g_span = mk_sp(span.lo(), fd.output.span().lo());
-    let generics_str = try_opt!(rewrite_generics(context, fn_sig.generics, shape, g_span));
+    let generics_str = rewrite_generics(context, fn_sig.generics, shape, g_span)?;
     result.push_str(&generics_str);
 
     let snuggle_angle_bracket = generics_str
@@ -1798,16 +1822,14 @@ fn rewrite_fn_base(
 
     // Note that the width and indent don't really matter, we'll re-layout the
     // return type later anyway.
-    let ret_str = try_opt!(
-        fd.output
-            .rewrite(context, Shape::indented(indent, context.config))
-    );
+    let ret_str = fd.output
+        .rewrite(context, Shape::indented(indent, context.config))?;
 
     let multi_line_ret_str = ret_str.contains('\n');
     let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() };
 
     // Args.
-    let (one_line_budget, multi_line_budget, mut arg_indent) = try_opt!(compute_budgets_for_args(
+    let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args(
         context,
         &result,
         indent,
@@ -1815,7 +1837,7 @@ fn rewrite_fn_base(
         newline_brace,
         has_body,
         multi_line_ret_str,
-    ));
+    )?;
 
     debug!(
         "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
@@ -1831,13 +1853,13 @@ fn rewrite_fn_base(
         } 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_layout() == IndentStyle::Visual {
+            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_layout() == IndentStyle::Visual {
+            if context.config.fn_args_indent() == IndentStyle::Visual {
                 result.push('\n');
                 result.push_str(&arg_indent.to_string(context.config));
             }
@@ -1849,12 +1871,14 @@ fn rewrite_fn_base(
         result.push(' ')
     }
 
+    // Skip `pub(crate)`.
+    let lo_after_visibility = get_bytepos_after_visibility(context, &fn_sig.visibility, span, ")");
     // A conservative estimation, to goal is to be over all parens in generics
     let args_start = fn_sig
         .generics
         .ty_params
         .last()
-        .map_or(span.lo(), |tp| end_typaram(tp));
+        .map_or(lo_after_visibility, |tp| end_typaram(tp));
     let args_end = if fd.inputs.is_empty() {
         context
             .codemap
@@ -1869,7 +1893,7 @@ fn rewrite_fn_base(
             .span_after(mk_sp(args_start, span.hi()), "("),
         args_end,
     );
-    let arg_str = try_opt!(rewrite_args(
+    let arg_str = rewrite_args(
         context,
         &fd.inputs,
         fd.get_self().as_ref(),
@@ -1880,9 +1904,9 @@ fn rewrite_fn_base(
         args_span,
         fd.variadic,
         generics_str.contains('\n'),
-    ));
+    )?;
 
-    let put_args_in_block = match context.config.fn_args_layout() {
+    let put_args_in_block = match context.config.fn_args_indent() {
         IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget,
         _ => false,
     } && !fd.inputs.is_empty();
@@ -1923,7 +1947,7 @@ fn rewrite_fn_base(
 
     // Return type.
     if let ast::FunctionRetTy::Ty(..) = fd.output {
-        let ret_should_indent = match context.config.fn_args_layout() {
+        let ret_should_indent = match context.config.fn_args_indent() {
             // 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,
@@ -1968,10 +1992,8 @@ fn rewrite_fn_base(
         if multi_line_ret_str || ret_should_indent {
             // Now that we know the proper indent and width, we need to
             // re-layout the return type.
-            let ret_str = try_opt!(
-                fd.output
-                    .rewrite(context, Shape::indented(ret_indent, context.config))
-            );
+            let ret_str = fd.output
+                .rewrite(context, Shape::indented(ret_indent, context.config))?;
             result.push_str(&ret_str);
         } else {
             result.push_str(&ret_str);
@@ -1985,7 +2007,7 @@ fn rewrite_fn_base(
             // Try to preserve the layout of the original snippet.
             let original_starts_with_newline = snippet
                 .find(|c| c != ' ')
-                .map_or(false, |i| snippet[i..].starts_with('\n'));
+                .map_or(false, |i| starts_with_newline(&snippet[i..]));
             let original_ends_with_newline = snippet
                 .rfind(|c| c != ' ')
                 .map_or(false, |i| snippet[i..].ends_with('\n'));
@@ -2015,6 +2037,8 @@ fn rewrite_fn_base(
         ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(),
     };
 
+    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(
@@ -2027,6 +2051,7 @@ fn rewrite_fn_base(
             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);
@@ -2035,7 +2060,7 @@ fn rewrite_fn_base(
     }
 
     let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty());
-    let where_clause_str = try_opt!(rewrite_where_clause(
+    let where_clause_str = rewrite_where_clause(
         context,
         where_clause,
         context.config.fn_brace_style(),
@@ -2045,7 +2070,8 @@ fn rewrite_fn_base(
         Some(span.hi()),
         pos_before_where,
         option,
-    ));
+        is_args_multi_lined,
+    )?;
     // If there are neither where clause nor return type, we may be missing comments between
     // args and `{`.
     if where_clause_str.is_empty() {
@@ -2068,6 +2094,7 @@ fn rewrite_fn_base(
     result.push_str(&where_clause_str);
 
     force_new_line_for_brace |= last_line_contains_single_line_comment(&result);
+    force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line();
     Some((result, force_new_line_for_brace))
 }
 
@@ -2116,13 +2143,11 @@ fn rewrite_args(
     variadic: bool,
     generics_str_contains_newline: bool,
 ) -> Option<String> {
-    let mut arg_item_strs = try_opt!(
-        args.iter()
-            .map(|arg| {
-                arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))
-            })
-            .collect::<Option<Vec<_>>>()
-    );
+    let mut arg_item_strs = args.iter()
+        .map(|arg| {
+            arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))
+        })
+        .collect::<Option<Vec<_>>>()?;
 
     // Account for sugary self.
     // FIXME: the comment for the self argument is dropped. This is blocked
@@ -2214,7 +2239,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_layout() {
+    let (indent, trailing_comma) = match context.config.fn_args_indent() {
         IndentStyle::Block if fits_in_one_line => {
             (indent.block_indent(context.config), SeparatorTactic::Never)
         }
@@ -2251,7 +2276,7 @@ enum ArgumentKind<'a> {
         },
         separator_place: SeparatorPlace::Back,
         shape: Shape::legacy(budget, indent),
-        ends_with_newline: tactic.ends_with_newline(context.config.fn_args_layout()),
+        ends_with_newline: tactic.ends_with_newline(context.config.fn_args_indent()),
         preserve_newline: true,
         config: context.config,
     };
@@ -2301,7 +2326,7 @@ fn compute_budgets_for_args(
 
         if one_line_budget > 0 {
             // 4 = "() {".len()
-            let (indent, multi_line_budget) = match context.config.fn_args_layout() {
+            let (indent, multi_line_budget) = match context.config.fn_args_indent() {
                 IndentStyle::Block => {
                     let indent = indent.block_indent(context.config);
                     (indent, context.budget(indent.width() + 1))
@@ -2319,7 +2344,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_layout() {
+    let used_space = match context.config.fn_args_indent() {
         // 1 = `,`
         IndentStyle::Block => new_indent.width() + 1,
         // Account for `)` and possibly ` {`.
@@ -2329,11 +2354,16 @@ fn compute_budgets_for_args(
 }
 
 fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause, has_body: bool) -> 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 where_clause.predicates.len() == 1 => false,
-        (_, Density::CompressedIfEmpty) if where_clause.predicates.len() == 1 && !has_body => false,
-        (BraceStyle::SameLineWhere, _) if !where_clause.predicates.is_empty() => 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,
     }
 }
@@ -2344,7 +2374,7 @@ fn rewrite_generics(
     shape: Shape,
     span: Span,
 ) -> Option<String> {
-    let g_shape = try_opt!(generics_shape_from_config(context.config, shape, 0));
+    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)
@@ -2369,16 +2399,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(),
             }
         }
     }
@@ -2452,7 +2482,7 @@ pub fn format_generics_item_list<I>(
         config: context.config,
     };
 
-    let list_str = try_opt!(write_list(&item_vec, &fmt));
+    let list_str = write_list(&item_vec, &fmt)?;
 
     Some(wrap_generics_with_angle_brackets(
         context,
@@ -2494,12 +2524,10 @@ fn rewrite_trait_bounds(
     if bounds.is_empty() {
         return Some(String::new());
     }
-    let bound_str = try_opt!(
-        bounds
-            .iter()
-            .map(|ty_bound| ty_bound.rewrite(context, shape))
-            .collect::<Option<Vec<_>>>()
-    );
+    let bound_str = bounds
+        .iter()
+        .map(|ty_bound| ty_bound.rewrite(context, shape))
+        .collect::<Option<Vec<_>>>()?;
     Some(format!(": {}", join_bounds(context, shape, &bound_str)))
 }
 
@@ -2511,17 +2539,14 @@ fn rewrite_where_clause_rfc_style(
     span_end: Option<BytePos>,
     span_end_before_where: BytePos,
     where_clause_option: WhereClauseOption,
+    is_args_multi_line: bool,
 ) -> Option<String> {
     let block_shape = shape.block().with_max_width(context.config);
 
     let (span_before, span_after) =
         missing_span_before_after_where(span_end_before_where, where_clause);
-    let (comment_before, comment_after) = try_opt!(rewrite_comments_before_after_where(
-        context,
-        span_before,
-        span_after,
-        shape,
-    ));
+    let (comment_before, comment_after) =
+        rewrite_comments_before_after_where(context, span_before, span_after, shape)?;
 
     let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() {
         " ".to_owned()
@@ -2529,7 +2554,9 @@ fn rewrite_where_clause_rfc_style(
         "\n".to_owned() + &block_shape.indent.to_string(context.config)
     };
 
-    let clause_shape = block_shape.block_indent(context.config.tab_spaces());
+    let clause_shape = block_shape.block_left(context.config.tab_spaces())?;
+    // 1 = `,`
+    let clause_shape = clause_shape.sub_width(1)?;
     // each clause on one line, trailing comma (except if suppress_comma)
     let span_start = where_clause.predicates[0].span().lo();
     // If we don't have the start of the next span, then use the end of the
@@ -2543,19 +2570,28 @@ fn rewrite_where_clause_rfc_style(
         terminator,
         |pred| pred.span().lo(),
         |pred| pred.span().hi(),
-        |pred| pred.rewrite(context, block_shape),
+        |pred| pred.rewrite(context, clause_shape),
         span_start,
         span_end,
         false,
     );
-    let comma_tactic = if where_clause_option.suppress_comma {
+    let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line;
+    let comma_tactic = if where_clause_option.suppress_comma || where_single_line {
         SeparatorTactic::Never
     } else {
         context.config.trailing_comma()
     };
 
+    // shape should be vertical only and only if we have `where_single_line` option enabled
+    // and the number of items of the where clause is equal to 1
+    let shape_tactic = if where_single_line {
+        DefinitiveListTactic::Horizontal
+    } else {
+        DefinitiveListTactic::Vertical
+    };
+
     let fmt = ListFormatting {
-        tactic: DefinitiveListTactic::Vertical,
+        tactic: shape_tactic,
         separator: ",",
         trailing_separator: comma_tactic,
         separator_place: SeparatorPlace::Back,
@@ -2564,7 +2600,7 @@ fn rewrite_where_clause_rfc_style(
         preserve_newline: true,
         config: context.config,
     };
-    let preds_str = try_opt!(write_list(&items.collect::<Vec<_>>(), &fmt));
+    let preds_str = write_list(&items.collect::<Vec<_>>(), &fmt)?;
 
     let comment_separator = |comment: &str, shape: Shape| if comment.is_empty() {
         String::new()
@@ -2577,7 +2613,7 @@ fn rewrite_where_clause_rfc_style(
     // 6 = `where `
     let clause_sep = if where_clause_option.compress_where && comment_before.is_empty()
         && comment_after.is_empty() && !preds_str.contains('\n')
-        && 6 + preds_str.len() <= shape.width
+        && 6 + preds_str.len() <= shape.width || where_single_line
     {
         String::from(" ")
     } else {
@@ -2605,6 +2641,7 @@ fn rewrite_where_clause(
     span_end: Option<BytePos>,
     span_end_before_where: BytePos,
     where_clause_option: WhereClauseOption,
+    is_args_multi_line: bool,
 ) -> Option<String> {
     if where_clause.predicates.is_empty() {
         return Some(String::new());
@@ -2619,6 +2656,7 @@ fn rewrite_where_clause(
             span_end,
             span_end_before_where,
             where_clause_option,
+            is_args_multi_line,
         );
     }
 
@@ -2676,7 +2714,7 @@ fn rewrite_where_clause(
         preserve_newline: true,
         config: context.config,
     };
-    let preds_str = try_opt!(write_list(&item_vec, &fmt));
+    let preds_str = write_list(&item_vec, &fmt)?;
 
     let end_length = if terminator == "{" {
         // If the brace is on the next line we don't need to count it otherwise it needs two
@@ -2720,12 +2758,12 @@ fn rewrite_comments_before_after_where(
     span_after_where: Span,
     shape: Shape,
 ) -> Option<(String, String)> {
-    let before_comment = try_opt!(rewrite_missing_comment(span_before_where, shape, context));
-    let after_comment = try_opt!(rewrite_missing_comment(
+    let before_comment = rewrite_missing_comment(span_before_where, shape, context)?;
+    let after_comment = rewrite_missing_comment(
         span_after_where,
         shape.block_indent(context.config.tab_spaces()),
         context,
-    ));
+    )?;
     Some((before_comment, after_comment))
 }
 
@@ -2736,8 +2774,6 @@ fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> S
 fn format_generics(
     context: &RewriteContext,
     generics: &ast::Generics,
-    opener: &str,
-    terminator: &str,
     brace_style: BraceStyle,
     force_same_line_brace: bool,
     offset: Indent,
@@ -2745,22 +2781,30 @@ fn format_generics(
     used_width: usize,
 ) -> Option<String> {
     let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
-    let mut result = try_opt!(rewrite_generics(context, generics, shape, span));
+    let mut result = rewrite_generics(context, generics, shape, span)?;
 
     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 where_clause_str = try_opt!(rewrite_where_clause(
+        // 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() {
+            generics.span.hi()
+        } else {
+            span.lo()
+        };
+        let where_clause_str = rewrite_where_clause(
             context,
             &generics.where_clause,
             brace_style,
             Shape::legacy(budget, offset.block_only()),
             Density::Tall,
-            terminator,
+            "{",
             Some(span.hi()),
-            generics.span.hi(),
+            span_end_before_where,
             option,
-        ));
+            false,
+        )?;
         result.push_str(&where_clause_str);
         force_same_line_brace || brace_style == BraceStyle::PreferSameLine
             || (generics.where_clause.predicates.is_empty()
@@ -2775,9 +2819,11 @@ fn format_generics(
     // 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()
+        // 3 = ` {}`
+        3
     } else {
-        1 + opener.len()
+        // 2 = ` {`
+        2
     };
     let forbid_same_line_brace = overhead > remaining_budget;
     if !forbid_same_line_brace && same_line_brace {
@@ -2786,19 +2832,19 @@ fn format_generics(
         result.push('\n');
         result.push_str(&offset.block_only().to_string(context.config));
     }
-    result.push_str(opener);
+    result.push('{');
 
     Some(result)
 }
 
 impl Rewrite for ast::ForeignItem {
     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
-        let attrs_str = try_opt!(self.attrs.rewrite(context, shape));
+        let attrs_str = self.attrs.rewrite(context, shape)?;
         // Drop semicolon or it will be interpreted as comment.
         // FIXME: this may be a faulty span from libsyntax.
         let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1));
 
-        let item_str = try_opt!(match self.node {
+        let item_str = match self.node {
             ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => {
                 rewrite_fn_base(
                     context,
@@ -2817,7 +2863,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                 let mut_str = if is_mutable { "mut " } else { "" };
                 let prefix = format!("{}static {}{}:", vis, mut_str, self.ident);
                 // 1 = ;
-                let shape = try_opt!(shape.sub_width(1));
+                let shape = shape.sub_width(1)?;
                 ty.rewrite(context, shape).map(|ty_str| {
                     // 1 = space between prefix and type.
                     let sep = if prefix.len() + ty_str.len() + 1 <= shape.width {
@@ -2829,7 +2875,11 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
                     format!("{}{}{};", prefix, sep, ty_str)
                 })
             }
-        });
+            ast::ForeignItemKind::Ty => {
+                let vis = format_visibility(&self.vis);
+                Some(format!("{}type {};", vis, self.ident))
+            }
+        }?;
 
         let missing_span = if self.attrs.is_empty() {
             mk_sp(self.span.lo(), self.span.lo())