diff --git a/src/expr.rs b/src/expr.rs
index bb4caaa7b93..a188634f98f 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -592,10 +592,7 @@ fn rewrite_closure(capture: ast::CaptureBy,
 
         // The body of the closure is big enough to be block indented, that
         // means we must re-format.
-        let block_shape = Shape {
-            width: context.config.max_width - shape.block().indent.width(),
-            ..shape.block()
-        };
+        let block_shape = shape.block().with_max_width(context.config);
         let block_str = try_opt!(block.rewrite(&context, block_shape));
         Some(format!("{} {}",
                      prefix,
@@ -1212,11 +1209,7 @@ fn rewrite_match(context: &RewriteContext,
         result.push('\n');
         result.push_str(&arm_indent_str);
 
-        let arm_str = arm.rewrite(&context,
-                                  Shape {
-                                      width: context.config.max_width - arm_shape.indent.width(),
-                                      ..arm_shape
-                                  });
+        let arm_str = arm.rewrite(&context, arm_shape.with_max_width(context.config));
         if let Some(ref arm_str) = arm_str {
             result.push_str(arm_str);
         } else {
@@ -1323,10 +1316,7 @@ impl Rewrite for ast::Arm {
         let pats_str = try_opt!(write_list(items, &fmt));
 
         let guard_shape = if pats_str.contains('\n') {
-            Shape {
-                width: context.config.max_width - shape.indent.width(),
-                ..shape
-            }
+            shape.with_max_width(context.config)
         } else {
             shape
         };
diff --git a/src/items.rs b/src/items.rs
index 0b2ca5a52cb..4b49d0a93f9 100644
--- a/src/items.rs
+++ b/src/items.rs
@@ -208,8 +208,8 @@ impl<'a> FmtVisitor<'a> {
                 let prefix = format!("{}static {}{}: ", vis, mut_str, item.ident);
                 let offset = self.block_indent + prefix.len();
                 // 1 = ;
-                let width = self.config.max_width - offset.width() - 1;
-                let rewrite = ty.rewrite(&self.get_context(), Shape::legacy(width, offset));
+                let shape = Shape::indented(offset, self.config).sub_width(1).unwrap();
+                let rewrite = ty.rewrite(&self.get_context(), shape);
 
                 match rewrite {
                     Some(result) => {
@@ -332,17 +332,13 @@ impl<'a> FmtVisitor<'a> {
                             let suffix = if semicolon_for_expr(e) { ";" } else { "" };
 
                             e.rewrite(&self.get_context(),
-                                         Shape::legacy(self.config.max_width -
-                                                       self.block_indent.width(),
-                                                       self.block_indent))
+                                         Shape::indented(self.block_indent, self.config))
                                 .map(|s| s + suffix)
                                 .or_else(|| Some(self.snippet(e.span)))
                         }
                         None => {
                             stmt.rewrite(&self.get_context(),
-                                         Shape::legacy(self.config.max_width -
-                                                       self.block_indent.width(),
-                                                       self.block_indent))
+                                         Shape::indented(self.block_indent, self.config))
                         }
                     }
                 } else {
@@ -434,12 +430,14 @@ impl<'a> FmtVisitor<'a> {
                                  body_lo,
                                  body_hi);
 
-        let budget = self.config.max_width - self.block_indent.width() - 2;
+        let shape = Shape::indented(self.block_indent, self.config)
+            .sub_width(2)
+            .unwrap();
         let fmt = ListFormatting {
             tactic: DefinitiveListTactic::Vertical,
             separator: ",",
             trailing_separator: self.config.trailing_comma,
-            shape: Shape::legacy(budget, self.block_indent),
+            shape: shape,
             ends_with_newline: true,
             config: self.config,
         };
@@ -463,9 +461,7 @@ impl<'a> FmtVisitor<'a> {
                                       .node
                                       .attrs
                                       .rewrite(&self.get_context(),
-                                               Shape::legacy(self.config.max_width -
-                                                             indent.width(),
-                                                             indent)));
+                                               Shape::indented(indent, self.config)));
         if !result.is_empty() {
             result.push('\n');
             result.push_str(&indent.to_string(self.config));
@@ -495,7 +491,7 @@ impl<'a> FmtVisitor<'a> {
 
                 wrap_str(tag,
                          self.config.max_width,
-                         Shape::legacy(self.config.max_width - indent.width(), indent))
+                         Shape::indented(indent, self.config))
             }
         };
 
@@ -643,7 +639,7 @@ fn format_impl_ref_and_type(context: &RewriteContext,
             None => self_ty.span.lo,
         };
         let generics_indent = offset + last_line_width(&result);
-        let shape = try_opt!(generics_shape(context.config, generics_indent));
+        let shape = Shape::indented(generics_indent, context.config);
         let generics_str = try_opt!(rewrite_generics(context, generics, shape, mk_sp(lo, hi)));
         result.push_str(&generics_str);
 
@@ -697,8 +693,8 @@ fn format_impl_ref_and_type(context: &RewriteContext,
         // Can't fit the self type on what's left of the line, so start a new one.
         let indent = offset.block_indent(context.config);
         result.push_str(&format!("\n{}", indent.to_string(context.config)));
-        let budget = try_opt!(context.config.max_width.checked_sub(indent.width()));
-        result.push_str(&*try_opt!(self_ty.rewrite(context, Shape::legacy(budget, indent))));
+        result.push_str(&*try_opt!(self_ty.rewrite(context,
+                                                   Shape::indented(indent, context.config))));
         Some(result)
     } else {
         unreachable!();
@@ -755,7 +751,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
         let body_lo = context.codemap.span_after(item.span, "{");
 
         let generics_indent = offset + last_line_width(&result);
-        let shape = try_opt!(generics_shape(context.config, generics_indent));
+        let shape = Shape::indented(generics_indent, context.config);
         let generics_str =
             try_opt!(rewrite_generics(context, generics, shape, mk_sp(item.span.lo, body_lo)));
         result.push_str(&generics_str);
@@ -1000,7 +996,7 @@ fn format_tuple_struct(context: &RewriteContext,
     let where_clause_str = match generics {
         Some(generics) => {
             let generics_indent = offset + last_line_width(&header_str);
-            let shape = try_opt!(generics_shape(context.config, generics_indent));
+            let shape = Shape::indented(generics_indent, context.config);
             let generics_str =
                 try_opt!(rewrite_generics(context, generics, shape, mk_sp(span.lo, body_lo)));
             result.push_str(&generics_str);
@@ -1131,7 +1127,7 @@ pub fn rewrite_type_alias(context: &RewriteContext,
 
     let generics_indent = indent + result.len();
     let generics_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo);
-    let shape = try_opt!(try_opt!(generics_shape(context.config, generics_indent))
+    let shape = try_opt!(Shape::indented(generics_indent, context.config)
                              .sub_width(" =".len()));
     let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span));
 
@@ -1205,11 +1201,9 @@ impl Rewrite for ast::StructField {
 
         let name = self.ident;
         let vis = format_visibility(&self.vis);
-        let mut attr_str = try_opt!(self.attrs
-                                        .rewrite(context,
-                                                 Shape::legacy(context.config.max_width -
-                                                               shape.indent.width(),
-                                                               shape.indent)));
+        let mut attr_str =
+            try_opt!(self.attrs
+                         .rewrite(context, Shape::indented(shape.indent, context.config)));
         if !attr_str.is_empty() {
             attr_str.push('\n');
             attr_str.push_str(&shape.indent.to_string(context.config));
@@ -1223,8 +1217,8 @@ impl Rewrite for ast::StructField {
 
         let type_offset = shape.indent.block_indent(context.config);
         let rewrite_type_in_next_line = || {
-            let budget = try_opt!(context.config.max_width.checked_sub(type_offset.width()));
-            self.ty.rewrite(context, Shape::legacy(budget, type_offset))
+            self.ty
+                .rewrite(context, Shape::indented(type_offset, context.config))
         };
 
         let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len();
@@ -1555,7 +1549,7 @@ fn rewrite_fn_base(context: &RewriteContext,
     // Generics.
     let generics_indent = indent + last_line_width(&result);
     let generics_span = mk_sp(span.lo, span_for_return(&fd.output).lo);
-    let shape = try_opt!(generics_shape(context.config, generics_indent));
+    let shape = Shape::indented(generics_indent, context.config);
     let generics_str = try_opt!(rewrite_generics(context, generics, shape, generics_span));
     result.push_str(&generics_str);
 
@@ -1564,10 +1558,7 @@ fn rewrite_fn_base(context: &RewriteContext,
     // 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::legacy(context.config.max_width -
-                                                      indent.width(),
-                                                      indent)));
+                               .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() };
@@ -1701,9 +1692,9 @@ fn rewrite_fn_base(context: &RewriteContext,
         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 budget = try_opt!(context.config.max_width.checked_sub(ret_indent.width()));
             let ret_str = try_opt!(fd.output
-                                       .rewrite(context, Shape::legacy(budget, ret_indent)));
+                                       .rewrite(context,
+                                                Shape::indented(ret_indent, context.config)));
             result.push_str(&ret_str);
         } else {
             result.push_str(&ret_str);
@@ -1759,11 +1750,10 @@ fn rewrite_fn_base(context: &RewriteContext,
         }
     }
 
-    let budget = try_opt!(context.config.max_width.checked_sub(indent.block_indent));
     let where_clause_str = try_opt!(rewrite_where_clause(context,
                                                          where_clause,
                                                          context.config.fn_brace_style,
-                                                         Shape::legacy(budget, indent),
+                                                         Shape::indented(indent, context.config),
                                                          Density::Tall,
                                                          "{",
                                                          !has_braces,
@@ -2226,7 +2216,7 @@ fn format_generics(context: &RewriteContext,
                    offset: Indent,
                    span: Span)
                    -> Option<String> {
-    let shape = try_opt!(generics_shape(context.config, offset));
+    let shape = Shape::indented(offset, context.config);
     let mut result = try_opt!(rewrite_generics(context, generics, shape, span));
 
     if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
@@ -2269,8 +2259,3 @@ fn format_generics(context: &RewriteContext,
 
     Some(result)
 }
-
-fn generics_shape(config: &Config, indent: Indent) -> Option<Shape> {
-    Some(Shape::legacy(try_opt!(config.max_width.checked_sub(indent.width())),
-                       indent))
-}
diff --git a/src/lib.rs b/src/lib.rs
index a3f1a93ca48..13b2df06740 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -223,14 +223,6 @@ pub struct Shape {
 }
 
 impl Shape {
-    pub fn indented(indent: Indent, config: &Config) -> Shape {
-        Shape {
-            width: config.max_width,
-            indent: indent,
-            offset: indent.width(),
-        }
-    }
-
     /// `indent` is the indentation of the first line. The next lines
     /// should begin with at least `indent` spaces (except backwards
     /// indentation). The first line should not begin with indentation.
@@ -254,6 +246,24 @@ impl Shape {
         }
     }
 
+    pub fn indented(indent: Indent, config: &Config) -> Shape {
+        Shape {
+            width: config.max_width.checked_sub(indent.width()).unwrap_or(0),
+            indent: indent,
+            offset: indent.alignment,
+        }
+    }
+
+    pub fn with_max_width(&self, config: &Config) -> Shape {
+        Shape {
+            width: config
+                .max_width
+                .checked_sub(self.indent.width())
+                .unwrap_or(0),
+            ..*self
+        }
+    }
+
     pub fn offset(width: usize, indent: Indent, offset: usize) -> Shape {
         Shape {
             width: width,
@@ -288,34 +298,27 @@ impl Shape {
     }
 
     pub fn block_left(&self, width: usize) -> Option<Shape> {
-        let block_shape = self.block_indent(width);
-        Some(Shape {
-                 width: try_opt!(block_shape.width.checked_sub(width)),
-                 ..block_shape
-             })
+        self.block_indent(width).sub_width(width)
     }
 
     pub fn add_offset(&self, extra_width: usize) -> Shape {
         Shape {
-            width: self.width,
-            indent: self.indent,
             offset: self.offset + extra_width,
+            ..*self
         }
     }
 
     pub fn block(&self) -> Shape {
         Shape {
-            width: self.width,
             indent: self.indent.block_only(),
-            offset: self.offset,
+            ..*self
         }
     }
 
     pub fn sub_width(&self, width: usize) -> Option<Shape> {
         Some(Shape {
                  width: try_opt!(self.width.checked_sub(width)),
-                 indent: self.indent,
-                 offset: self.offset,
+                 ..*self
              })
     }
 
@@ -328,11 +331,7 @@ impl Shape {
     }
 
     pub fn offset_left(&self, width: usize) -> Option<Shape> {
-        Some(Shape {
-                 width: try_opt!(self.width.checked_sub(width)),
-                 indent: self.indent,
-                 offset: self.offset + width,
-             })
+        self.add_offset(width).sub_width(width)
     }
 
     pub fn used_width(&self) -> usize {
@@ -712,20 +711,20 @@ mod test {
     fn shape_visual_indent() {
         let config = Config::default();
         let indent = Indent::new(4, 8);
-        let shape = Shape::indented(indent, &config);
+        let shape = Shape::legacy(config.max_width, indent);
         let shape = shape.visual_indent(20);
 
         assert_eq!(config.max_width, shape.width);
         assert_eq!(4, shape.indent.block_indent);
-        assert_eq!(32, shape.indent.alignment);
-        assert_eq!(32, shape.offset);
+        assert_eq!(28, shape.indent.alignment);
+        assert_eq!(28, shape.offset);
     }
 
     #[test]
     fn shape_block_indent_without_alignment() {
         let config = Config::default();
         let indent = Indent::new(4, 0);
-        let shape = Shape::indented(indent, &config);
+        let shape = Shape::legacy(config.max_width, indent);
         let shape = shape.block_indent(20);
 
         assert_eq!(config.max_width, shape.width);
@@ -738,7 +737,7 @@ mod test {
     fn shape_block_indent_with_alignment() {
         let config = Config::default();
         let indent = Indent::new(4, 8);
-        let shape = Shape::indented(indent, &config);
+        let shape = Shape::legacy(config.max_width, indent);
         let shape = shape.block_indent(20);
 
         assert_eq!(config.max_width, shape.width);
diff --git a/src/visitor.rs b/src/visitor.rs
index e2003d1653a..38185047b7e 100644
--- a/src/visitor.rs
+++ b/src/visitor.rs
@@ -62,10 +62,9 @@ impl<'a> FmtVisitor<'a> {
             ast::StmtKind::Local(..) |
             ast::StmtKind::Expr(..) |
             ast::StmtKind::Semi(..) => {
-                let rewrite = stmt.rewrite(&self.get_context(),
-                                           Shape::legacy(self.config.max_width -
-                                                         self.block_indent.width(),
-                                                         self.block_indent));
+                let rewrite =
+                    stmt.rewrite(&self.get_context(),
+                                 Shape::indented(self.block_indent, self.config));
                 if rewrite.is_none() {
                     self.failed = true;
                 }
@@ -456,10 +455,7 @@ impl<'a> FmtVisitor<'a> {
             codemap: parse_session.codemap(),
             buffer: StringBuffer::new(),
             last_pos: BytePos(0),
-            block_indent: Indent {
-                block_indent: 0,
-                alignment: 0,
-            },
+            block_indent: Indent::empty(),
             config: config,
             failed: false,
         }
@@ -497,8 +493,7 @@ impl<'a> FmtVisitor<'a> {
 
         let rewrite = outers
             .rewrite(&self.get_context(),
-                     Shape::legacy(self.config.max_width - self.block_indent.width(),
-                                   self.block_indent))
+                     Shape::indented(self.block_indent, self.config))
             .unwrap();
         self.buffer.push_str(&rewrite);
         let last = outers.last().unwrap();