diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 625acce27bd64..eef530081abe3 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -42,7 +42,7 @@ pub struct UnsafetySpace(pub hir::Unsafety);
 #[derive(Copy, Clone)]
 pub struct ConstnessSpace(pub hir::Constness);
 /// Wrapper struct for properly emitting a method declaration.
-pub struct Method<'a>(pub &'a clean::FnDecl, pub &'a str);
+pub struct Method<'a>(pub &'a clean::FnDecl, pub usize);
 /// Similar to VisSpace, but used for mutability
 #[derive(Copy, Clone)]
 pub struct MutableSpace(pub clean::Mutability);
@@ -50,7 +50,7 @@ pub struct MutableSpace(pub clean::Mutability);
 #[derive(Copy, Clone)]
 pub struct RawMutableSpace(pub clean::Mutability);
 /// Wrapper struct for emitting a where clause from Generics.
-pub struct WhereClause<'a>(pub &'a clean::Generics);
+pub struct WhereClause<'a>(pub &'a clean::Generics, pub usize);
 /// Wrapper struct for emitting type parameter bounds.
 pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]);
 /// Wrapper struct for emitting a comma-separated list of items
@@ -157,52 +157,71 @@ impl fmt::Display for clean::Generics {
 
 impl<'a> fmt::Display for WhereClause<'a> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let &WhereClause(gens) = self;
+        let &WhereClause(gens, pad) = self;
         if gens.where_predicates.is_empty() {
             return Ok(());
         }
+        let mut clause = String::new();
         if f.alternate() {
-            f.write_str(" ")?;
+            clause.push_str(" where ");
         } else {
-            f.write_str(" <span class='where'>where ")?;
+            clause.push_str(" <span class='where'>where ");
         }
         for (i, pred) in gens.where_predicates.iter().enumerate() {
             if i > 0 {
-                f.write_str(", ")?;
+                if f.alternate() {
+                    clause.push_str(", ");
+                } else {
+                    clause.push_str(",<br>");
+                }
             }
             match pred {
                 &clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => {
                     let bounds = bounds;
                     if f.alternate() {
-                        write!(f, "{:#}: {:#}", ty, TyParamBounds(bounds))?;
+                        clause.push_str(&format!("{:#}: {:#}", ty, TyParamBounds(bounds)));
                     } else {
-                        write!(f, "{}: {}", ty, TyParamBounds(bounds))?;
+                        clause.push_str(&format!("{}: {}", ty, TyParamBounds(bounds)));
                     }
                 }
                 &clean::WherePredicate::RegionPredicate { ref lifetime,
                                                           ref bounds } => {
-                    write!(f, "{}: ", lifetime)?;
+                    clause.push_str(&format!("{}: ", lifetime));
                     for (i, lifetime) in bounds.iter().enumerate() {
                         if i > 0 {
-                            f.write_str(" + ")?;
+                            clause.push_str(" + ");
                         }
 
-                        write!(f, "{}", lifetime)?;
+                        clause.push_str(&format!("{}", lifetime));
                     }
                 }
                 &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
                     if f.alternate() {
-                        write!(f, "{:#} == {:#}", lhs, rhs)?;
+                        clause.push_str(&format!("{:#} == {:#}", lhs, rhs));
                     } else {
-                        write!(f, "{} == {}", lhs, rhs)?;
+                        clause.push_str(&format!("{} == {}", lhs, rhs));
                     }
                 }
             }
         }
         if !f.alternate() {
-            f.write_str("</span>")?;
+            clause.push_str("</span>");
+            let plain = format!("{:#}", self);
+            if plain.len() > 80 {
+                //break it onto its own line regardless, but make sure method impls and trait
+                //blocks keep their fixed padding (2 and 9, respectively)
+                let padding = if pad > 10 {
+                    clause = clause.replace("class='where'", "class='where fmt-newline'");
+                    repeat("&nbsp;").take(8).collect::<String>()
+                } else {
+                    repeat("&nbsp;").take(pad + 6).collect::<String>()
+                };
+                clause = clause.replace("<br>", &format!("<br>{}", padding));
+            } else {
+                clause = clause.replace("<br>", " ");
+            }
         }
-        Ok(())
+        write!(f, "{}", clause)
     }
 }
 
@@ -718,30 +737,43 @@ impl fmt::Display for clean::Type {
 }
 
 fn fmt_impl(i: &clean::Impl, f: &mut fmt::Formatter, link_trait: bool) -> fmt::Result {
+    let mut plain = String::new();
+
     if f.alternate() {
         write!(f, "impl{:#} ", i.generics)?;
     } else {
         write!(f, "impl{} ", i.generics)?;
     }
+    plain.push_str(&format!("impl{:#} ", i.generics));
+
     if let Some(ref ty) = i.trait_ {
-        write!(f, "{}",
-               if i.polarity == Some(clean::ImplPolarity::Negative) { "!" } else { "" })?;
+        if i.polarity == Some(clean::ImplPolarity::Negative) {
+            write!(f, "!")?;
+            plain.push_str("!");
+        }
+
         if link_trait {
             fmt::Display::fmt(ty, f)?;
+            plain.push_str(&format!("{:#}", ty));
         } else {
             match *ty {
                 clean::ResolvedPath{ typarams: None, ref path, is_generic: false, .. } => {
                     let last = path.segments.last().unwrap();
                     fmt::Display::fmt(&last.name, f)?;
                     fmt::Display::fmt(&last.params, f)?;
+                    plain.push_str(&format!("{:#}{:#}", last.name, last.params));
                 }
                 _ => unreachable!(),
             }
         }
         write!(f, " for ")?;
+        plain.push_str(" for ");
     }
+
     fmt::Display::fmt(&i.for_, f)?;
-    fmt::Display::fmt(&WhereClause(&i.generics), f)?;
+    plain.push_str(&format!("{:#}", i.for_));
+
+    fmt::Display::fmt(&WhereClause(&i.generics, plain.len() + 1), f)?;
     Ok(())
 }
 
@@ -870,24 +902,30 @@ impl<'a> fmt::Display for Method<'a> {
 
         let mut output: String;
         let plain: String;
+        let pad = repeat(" ").take(indent).collect::<String>();
         if arrow.is_empty() {
             output = format!("({})", args);
-            plain = format!("{}({})", indent.replace("&nbsp;", " "), args_plain);
+            plain = format!("{}({})", pad, args_plain);
         } else {
             output = format!("({args})<br>{arrow}", args = args, arrow = arrow);
-            plain = format!("{indent}({args}){arrow}",
-                            indent = indent.replace("&nbsp;", " "),
+            plain = format!("{pad}({args}){arrow}",
+                            pad = pad,
                             args = args_plain,
                             arrow = arrow_plain);
         }
 
         if plain.len() > 80 {
-            let pad = format!("<br>{}", indent);
+            let pad = repeat("&nbsp;").take(indent).collect::<String>();
+            let pad = format!("<br>{}", pad);
             output = output.replace("<br>", &pad);
         } else {
             output = output.replace("<br>", "");
         }
-        write!(f, "{}", output)
+        if f.alternate() {
+            write!(f, "{}", output.replace("<br>", "\n"))
+        } else {
+            write!(f, "{}", output)
+        }
     }
 }
 
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index d8dba00e7d578..c0a1abd4aec3f 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -1967,14 +1967,13 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         UnstableFeatures::Allow => f.constness,
         _ => hir::Constness::NotConst
     };
-    let prefix = format!("{}{}{}{:#}fn {}{:#}",
+    let indent = format!("{}{}{}{:#}fn {}{:#}",
                          VisSpace(&it.visibility),
                          ConstnessSpace(vis_constness),
                          UnsafetySpace(f.unsafety),
                          AbiSpace(f.abi),
                          it.name.as_ref().unwrap(),
-                         f.generics);
-    let indent = repeat("&nbsp;").take(prefix.len()).collect::<String>();
+                         f.generics).len();
     write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \
                {name}{generics}{decl}{where_clause}</pre>",
            vis = VisSpace(&it.visibility),
@@ -1983,22 +1982,29 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
            abi = AbiSpace(f.abi),
            name = it.name.as_ref().unwrap(),
            generics = f.generics,
-           where_clause = WhereClause(&f.generics),
-           decl = Method(&f.decl, &indent))?;
+           where_clause = WhereClause(&f.generics, 2),
+           decl = Method(&f.decl, indent))?;
     document(w, cx, it)
 }
 
 fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
               t: &clean::Trait) -> fmt::Result {
     let mut bounds = String::new();
+    let mut bounds_plain = String::new();
     if !t.bounds.is_empty() {
         if !bounds.is_empty() {
             bounds.push(' ');
+            bounds_plain.push(' ');
         }
         bounds.push_str(": ");
+        bounds_plain.push_str(": ");
         for (i, p) in t.bounds.iter().enumerate() {
-            if i > 0 { bounds.push_str(" + "); }
+            if i > 0 {
+                bounds.push_str(" + ");
+                bounds_plain.push_str(" + ");
+            }
             bounds.push_str(&format!("{}", *p));
+            bounds_plain.push_str(&format!("{:#}", *p));
         }
     }
 
@@ -2009,7 +2015,8 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
            it.name.as_ref().unwrap(),
            t.generics,
            bounds,
-           WhereClause(&t.generics))?;
+           // Where clauses in traits are indented nine spaces, per rustdoc.css
+           WhereClause(&t.generics, 9))?;
 
     let types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
     let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
@@ -2023,7 +2030,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         write!(w, "{{\n")?;
         for t in &types {
             write!(w, "    ")?;
-            render_assoc_item(w, t, AssocItemLink::Anchor(None))?;
+            render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
             write!(w, ";\n")?;
         }
         if !types.is_empty() && !consts.is_empty() {
@@ -2031,7 +2038,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for t in &consts {
             write!(w, "    ")?;
-            render_assoc_item(w, t, AssocItemLink::Anchor(None))?;
+            render_assoc_item(w, t, AssocItemLink::Anchor(None), ItemType::Trait)?;
             write!(w, ";\n")?;
         }
         if !consts.is_empty() && !required.is_empty() {
@@ -2039,7 +2046,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &required {
             write!(w, "    ")?;
-            render_assoc_item(w, m, AssocItemLink::Anchor(None))?;
+            render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
             write!(w, ";\n")?;
         }
         if !required.is_empty() && !provided.is_empty() {
@@ -2047,7 +2054,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &provided {
             write!(w, "    ")?;
-            render_assoc_item(w, m, AssocItemLink::Anchor(None))?;
+            render_assoc_item(w, m, AssocItemLink::Anchor(None), ItemType::Trait)?;
             write!(w, " {{ ... }}\n")?;
         }
         write!(w, "}}")?;
@@ -2068,7 +2075,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                id = id,
                stab = m.stability_class(),
                ns_id = ns_id)?;
-        render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)))?;
+        render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?;
         write!(w, "</code>")?;
         render_stability_since(w, m, t)?;
         write!(w, "</span></h3>")?;
@@ -2222,7 +2229,8 @@ fn render_stability_since(w: &mut fmt::Formatter,
 
 fn render_assoc_item(w: &mut fmt::Formatter,
                      item: &clean::Item,
-                     link: AssocItemLink) -> fmt::Result {
+                     link: AssocItemLink,
+                     parent: ItemType) -> fmt::Result {
     fn method(w: &mut fmt::Formatter,
               meth: &clean::Item,
               unsafety: hir::Unsafety,
@@ -2230,7 +2238,8 @@ fn render_assoc_item(w: &mut fmt::Formatter,
               abi: abi::Abi,
               g: &clean::Generics,
               d: &clean::FnDecl,
-              link: AssocItemLink)
+              link: AssocItemLink,
+              parent: ItemType)
               -> fmt::Result {
         let name = meth.name.as_ref().unwrap();
         let anchor = format!("#{}.{}", meth.type_(), name);
@@ -2260,7 +2269,16 @@ fn render_assoc_item(w: &mut fmt::Formatter,
                              AbiSpace(abi),
                              name,
                              *g);
-        let indent = repeat("&nbsp;").take(prefix.len()).collect::<String>();
+        let mut indent = prefix.len();
+        let where_indent = if parent == ItemType::Trait {
+            indent += 4;
+            8
+        } else if parent == ItemType::Impl {
+            2
+        } else {
+            let prefix = prefix + &format!("{:#}", Method(d, indent));
+            prefix.lines().last().unwrap().len() + 1
+        };
         write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
                ConstnessSpace(vis_constness),
@@ -2269,19 +2287,18 @@ fn render_assoc_item(w: &mut fmt::Formatter,
                href = href,
                name = name,
                generics = *g,
-               decl = Method(d, &indent),
-               where_clause = WhereClause(g))
+               decl = Method(d, indent),
+               where_clause = WhereClause(g, where_indent))
     }
     match item.inner {
         clean::StrippedItem(..) => Ok(()),
         clean::TyMethodItem(ref m) => {
             method(w, item, m.unsafety, hir::Constness::NotConst,
-                   m.abi, &m.generics, &m.decl, link)
+                   m.abi, &m.generics, &m.decl, link, parent)
         }
         clean::MethodItem(ref m) => {
             method(w, item, m.unsafety, m.constness,
-                   m.abi, &m.generics, &m.decl,
-                   link)
+                   m.abi, &m.generics, &m.decl, link, parent)
         }
         clean::AssociatedConstItem(ref ty, ref default) => {
             assoc_const(w, item, ty, default.as_ref(), link)
@@ -2378,11 +2395,15 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
              e: &clean::Enum) -> fmt::Result {
     write!(w, "<pre class='rust enum'>")?;
     render_attributes(w, it)?;
+    let padding = format!("{}enum {}{:#} ",
+                          VisSpace(&it.visibility),
+                          it.name.as_ref().unwrap(),
+                          e.generics).len();
     write!(w, "{}enum {}{}{}",
            VisSpace(&it.visibility),
            it.name.as_ref().unwrap(),
            e.generics,
-           WhereClause(&e.generics))?;
+           WhereClause(&e.generics, padding))?;
     if e.variants.is_empty() && !e.variants_stripped {
         write!(w, " {{}}")?;
     } else {
@@ -2517,17 +2538,23 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
                  fields: &[clean::Item],
                  tab: &str,
                  structhead: bool) -> fmt::Result {
+    let mut plain = String::new();
     write!(w, "{}{}{}",
            VisSpace(&it.visibility),
            if structhead {"struct "} else {""},
            it.name.as_ref().unwrap())?;
+    plain.push_str(&format!("{}{}{}",
+                            VisSpace(&it.visibility),
+                            if structhead {"struct "} else {""},
+                            it.name.as_ref().unwrap()));
     if let Some(g) = g {
+        plain.push_str(&format!("{:#}", g));
         write!(w, "{}", g)?
     }
     match ty {
         doctree::Plain => {
             if let Some(g) = g {
-                write!(w, "{}", WhereClause(g))?
+                write!(w, "{}", WhereClause(g, plain.len() + 1))?
             }
             let mut has_visible_fields = false;
             write!(w, " {{")?;
@@ -2556,30 +2583,35 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
         }
         doctree::Tuple => {
             write!(w, "(")?;
+            plain.push_str("(");
             for (i, field) in fields.iter().enumerate() {
                 if i > 0 {
                     write!(w, ", ")?;
+                    plain.push_str(", ");
                 }
                 match field.inner {
                     clean::StrippedItem(box clean::StructFieldItem(..)) => {
+                        plain.push_str("_");
                         write!(w, "_")?
                     }
                     clean::StructFieldItem(ref ty) => {
+                        plain.push_str(&format!("{}{:#}", VisSpace(&field.visibility), *ty));
                         write!(w, "{}{}", VisSpace(&field.visibility), *ty)?
                     }
                     _ => unreachable!()
                 }
             }
             write!(w, ")")?;
+            plain.push_str(")");
             if let Some(g) = g {
-                write!(w, "{}", WhereClause(g))?
+                write!(w, "{}", WhereClause(g, plain.len() + 1))?
             }
             write!(w, ";")?;
         }
         doctree::Unit => {
             // Needed for PhantomData.
             if let Some(g) = g {
-                write!(w, "{}", WhereClause(g))?
+                write!(w, "{}", WhereClause(g, plain.len() + 1))?
             }
             write!(w, ";")?;
         }
@@ -2592,13 +2624,19 @@ fn render_union(w: &mut fmt::Formatter, it: &clean::Item,
                 fields: &[clean::Item],
                 tab: &str,
                 structhead: bool) -> fmt::Result {
+    let mut plain = String::new();
     write!(w, "{}{}{}",
            VisSpace(&it.visibility),
            if structhead {"union "} else {""},
            it.name.as_ref().unwrap())?;
+    plain.push_str(&format!("{}{}{}",
+                            VisSpace(&it.visibility),
+                            if structhead {"union "} else {""},
+                            it.name.as_ref().unwrap()));
     if let Some(g) = g {
         write!(w, "{}", g)?;
-        write!(w, "{}", WhereClause(g))?;
+        plain.push_str(&format!("{:#}", g));
+        write!(w, "{}", WhereClause(g, plain.len() + 1))?;
     }
 
     write!(w, " {{\n{}", tab)?;
@@ -2789,7 +2827,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
                     write!(w, "<h4 id='{}' class='{}'>", id, item_type)?;
                     write!(w, "<span id='{}' class='invisible'>", ns_id)?;
                     write!(w, "<code>")?;
-                    render_assoc_item(w, item, link.anchor(&id))?;
+                    render_assoc_item(w, item, link.anchor(&id), ItemType::Impl)?;
                     write!(w, "</code>")?;
                     render_stability_since_raw(w, item.stable_since(), outer_version)?;
                     write!(w, "</span></h4>\n")?;
@@ -2899,10 +2937,11 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
 
 fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                 t: &clean::Typedef) -> fmt::Result {
+    let indent = format!("type {}{:#} ", it.name.as_ref().unwrap(), t.generics).len();
     write!(w, "<pre class='rust typedef'>type {}{}{where_clause} = {type_};</pre>",
            it.name.as_ref().unwrap(),
            t.generics,
-           where_clause = WhereClause(&t.generics),
+           where_clause = WhereClause(&t.generics, indent),
            type_ = t.type_)?;
 
     document(w, cx, it)
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index f8133ea49ceba..3b6ffa4a462f6 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -361,9 +361,17 @@ h4 > code, h3 > code, .invisible > code {
     position: relative;
 }
 /* Shift "where ..." part of method or fn definition down a line */
-.content .method .where, .content .fn .where { display: block; }
+.content .method .where,
+.content .fn .where,
+.content .where.fmt-newline {
+    display: block;
+}
 /* Bit of whitespace to indent it */
-.content .method .where::before, .content .fn .where::before { content: '  '; }
+.content .method .where::before,
+.content .fn .where::before,
+.content .where.fmt-newline::before {
+    content: '  ';
+}
 
 .content .methods > div { margin-left: 40px; }
 
diff --git a/src/test/rustdoc/line-breaks.rs b/src/test/rustdoc/line-breaks.rs
index cc608a2447574..a1eabb515a5ce 100644
--- a/src/test/rustdoc/line-breaks.rs
+++ b/src/test/rustdoc/line-breaks.rs
@@ -10,6 +10,9 @@
 
 #![crate_name = "foo"]
 
+use std::ops::Add;
+use std::fmt::Display;
+
 //@count foo/fn.function_with_a_really_long_name.html //pre/br 2
 pub fn function_with_a_really_long_name(parameter_one: i32,
                                         parameter_two: i32)
@@ -19,3 +22,19 @@ pub fn function_with_a_really_long_name(parameter_one: i32,
 
 //@count foo/fn.short_name.html //pre/br 0
 pub fn short_name(param: i32) -> i32 { param + 1 }
+
+//@count foo/fn.where_clause.html //pre/br 4
+pub fn where_clause<T, U>(param_one: T,
+                          param_two: U)
+    where T: Add<U> + Display + Copy,
+          U: Add<T> + Display + Copy,
+          T::Output: Display + Add<U::Output> + Copy,
+          <T::Output as Add<U::Output>>::Output: Display,
+          U::Output: Display + Copy
+{
+    let x = param_one + param_two;
+    println!("{} + {} = {}", param_one, param_two, x);
+    let y = param_two + param_one;
+    println!("{} + {} = {}", param_two, param_one, y);
+    println!("{} + {} = {}", x, y, x + y);
+}