about summary refs log tree commit diff
path: root/src/librustdoc
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-04-13 11:55:00 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-04-16 09:44:33 -0700
commit0a46933c4d81573e78ce16cd215ba155a3114fce (patch)
tree66e4e0f08fdeccc9854787943fadd692b83e6810 /src/librustdoc
parent5576b0558c7f46faa5331be72113238c677979b6 (diff)
downloadrust-0a46933c4d81573e78ce16cd215ba155a3114fce.tar.gz
rust-0a46933c4d81573e78ce16cd215ba155a3114fce.zip
rustdoc: Overhaul stability displays
This commit is an overhaul to how rustdoc deals with stability of the standard
library. The handling has all been revisited with respect to Rust's current
approach to stability in terms of implementation as well as the state of the
standard library today. The high level changes made were:

* Stable items now have no marker by default
* Color-based small stability markers have been removed
* Module listings now fade out unstable/deprecated items slightly
* Trait methods have a separate background color based on stability and also
  list the reason that they are unstable.
* `impl` blocks with stability no longer render at all. This may be re-added
  once the compiler recognizes stability on `impl` blocks.
* `impl` blocks no longer have stability of the methods implemente indicated
* The stability summary has been removed

Closes #15468
Closes #21674
Closes #24201
Diffstat (limited to 'src/librustdoc')
-rw-r--r--src/librustdoc/clean/mod.rs16
-rw-r--r--src/librustdoc/html/format.rs122
-rw-r--r--src/librustdoc/html/render.rs182
-rw-r--r--src/librustdoc/html/static/main.css59
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/librustdoc/stability_summary.rs199
6 files changed, 132 insertions, 447 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 72702dc8d94..8b65a7d6791 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -313,6 +313,22 @@ impl Item {
     pub fn is_fn(&self) -> bool {
         match self.inner { FunctionItem(..) => true, _ => false }
     }
+
+    pub fn stability_class(&self) -> String {
+        match self.stability {
+            Some(ref s) => {
+                let mut base = match s.level {
+                    attr::Unstable => "unstable".to_string(),
+                    attr::Stable => String::new(),
+                };
+                if s.deprecated_since.len() > 0 {
+                    base.push_str(" deprecated");
+                }
+                base
+            }
+            _ => String::new(),
+        }
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index d2dccca362e..8b6969f586e 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -23,10 +23,8 @@ use syntax::ast;
 use syntax::ast_util;
 
 use clean;
-use stability_summary::ModuleSummary;
 use html::item_type::ItemType;
 use html::render;
-use html::escape::Escape;
 use html::render::{cache, CURRENT_LOCATION_KEY};
 
 /// Helper to render an optional visibility with a space after it (if the
@@ -45,10 +43,6 @@ pub struct MutableSpace(pub clean::Mutability);
 /// Similar to VisSpace, but used for mutability
 #[derive(Copy, Clone)]
 pub struct RawMutableSpace(pub clean::Mutability);
-/// Wrapper struct for properly emitting the stability level.
-pub struct Stability<'a>(pub &'a Option<clean::Stability>);
-/// Wrapper struct for emitting the stability level concisely.
-pub struct ConciseStability<'a>(pub &'a Option<clean::Stability>);
 /// Wrapper struct for emitting a where clause from Generics.
 pub struct WhereClause<'a>(pub &'a clean::Generics);
 /// Wrapper struct for emitting type parameter bounds.
@@ -702,119 +696,3 @@ impl fmt::Display for AbiSpace {
         }
     }
 }
-
-impl<'a> fmt::Display for Stability<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let Stability(stab) = *self;
-        match *stab {
-            Some(ref stability) => {
-                let lvl = if stability.deprecated_since.is_empty() {
-                    format!("{}", stability.level)
-                } else {
-                    "Deprecated".to_string()
-                };
-                write!(f, "<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
-                       lvl = Escape(&*lvl),
-                       reason = Escape(&*stability.reason))
-            }
-            None => Ok(())
-        }
-    }
-}
-
-impl<'a> fmt::Display for ConciseStability<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let ConciseStability(stab) = *self;
-        match *stab {
-            Some(ref stability) => {
-                let lvl = if stability.deprecated_since.is_empty() {
-                    format!("{}", stability.level)
-                } else {
-                    "Deprecated".to_string()
-                };
-                write!(f, "<a class='stability {lvl}' title='{lvl}{colon}{reason}'></a>",
-                       lvl = Escape(&*lvl),
-                       colon = if !stability.reason.is_empty() { ": " } else { "" },
-                       reason = Escape(&*stability.reason))
-            }
-            None => {
-                write!(f, "<a class='stability Unmarked' title='No stability level'></a>")
-            }
-        }
-    }
-}
-
-impl fmt::Display for ModuleSummary {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fn fmt_inner<'a>(f: &mut fmt::Formatter,
-                         context: &mut Vec<&'a str>,
-                         m: &'a ModuleSummary)
-                     -> fmt::Result {
-            let cnt = m.counts;
-            let tot = cnt.total();
-            if tot == 0 { return Ok(()) }
-
-            context.push(&m.name);
-            let path = context.connect("::");
-
-            try!(write!(f, "<tr>"));
-            try!(write!(f, "<td><a href='{}'>{}</a></td>", {
-                            let mut url = context[1..].to_vec();
-                            url.push("index.html");
-                            url.connect("/")
-                        },
-                        path));
-            try!(write!(f, "<td class='summary-column'>"));
-            try!(write!(f, "<span class='summary Stable' \
-                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
-                        (100 * cnt.stable) as f64/tot as f64));
-            try!(write!(f, "<span class='summary Unstable' \
-                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
-                        (100 * cnt.unstable) as f64/tot as f64));
-            try!(write!(f, "<span class='summary Deprecated' \
-                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
-                        (100 * cnt.deprecated) as f64/tot as f64));
-            try!(write!(f, "<span class='summary Unmarked' \
-                            style='width: {:.4}%; display: inline-block'>&nbsp</span>",
-                        (100 * cnt.unmarked) as f64/tot as f64));
-            try!(write!(f, "</td></tr>"));
-
-            for submodule in &m.submodules {
-                try!(fmt_inner(f, context, submodule));
-            }
-            context.pop();
-            Ok(())
-        }
-
-        let mut context = Vec::new();
-
-        let tot = self.counts.total();
-        let (stable, unstable, deprecated, unmarked) = if tot == 0 {
-            (0, 0, 0, 0)
-        } else {
-            ((100 * self.counts.stable)/tot,
-             (100 * self.counts.unstable)/tot,
-             (100 * self.counts.deprecated)/tot,
-             (100 * self.counts.unmarked)/tot)
-        };
-
-        try!(write!(f,
-r"<h1 class='fqn'>Stability dashboard: crate <a class='mod' href='index.html'>{name}</a></h1>
-This dashboard summarizes the stability levels for all of the public modules of
-the crate, according to the total number of items at each level in the module and
-its children (percentages total for {name}):
-<blockquote>
-<a class='stability Stable'></a> stable ({}%),<br/>
-<a class='stability Unstable'></a> unstable ({}%),<br/>
-<a class='stability Deprecated'></a> deprecated ({}%),<br/>
-<a class='stability Unmarked'></a> unmarked ({}%)
-</blockquote>
-The counts do not include methods or trait
-implementations that are visible only through a re-exported type.",
-stable, unstable, deprecated, unmarked,
-name=self.name));
-        try!(write!(f, "<table>"));
-        try!(fmt_inner(f, &mut context, self));
-        write!(f, "</table>")
-    }
-}
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 5f4a3e74b65..c619421635d 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -56,19 +56,20 @@ use serialize::json::ToJson;
 use syntax::abi;
 use syntax::ast;
 use syntax::ast_util;
+use syntax::attr;
 use rustc::util::nodemap::NodeSet;
 
 use clean;
 use doctree;
 use fold::DocFolder;
-use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace, Stability};
-use html::format::{ConciseStability, TyParamBounds, WhereClause, href, AbiSpace};
+use html::escape::Escape;
+use html::format::{TyParamBounds, WhereClause, href, AbiSpace};
+use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
 use html::highlight;
 use html::item_type::ItemType;
 use html::layout;
 use html::markdown::Markdown;
 use html::markdown;
-use stability_summary;
 
 /// A pair of name and its optional document.
 pub type NameDoc = (String, Option<String>);
@@ -437,11 +438,8 @@ pub fn run(mut krate: clean::Crate,
     try!(write_shared(&cx, &krate, &*cache, index));
     let krate = try!(render_sources(&mut cx, krate));
 
-    // Crawl the crate, building a summary of the stability levels.
-    let summary = stability_summary::build(&krate);
-
     // And finally render the whole crate's documentation
-    cx.krate(krate, summary)
+    cx.krate(krate)
 }
 
 fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
@@ -645,8 +643,7 @@ fn write_shared(cx: &Context,
             // going on). If they're in different crates then the crate defining
             // the trait will be interested in our implementation.
             if imp.def_id.krate == did.krate { continue }
-            try!(write!(&mut f, r#""{}impl{} {}{} for {}","#,
-                        ConciseStability(&imp.stability),
+            try!(write!(&mut f, r#""impl{} {}{} for {}","#,
                         imp.generics,
                         if imp.polarity == Some(clean::ImplPolarity::Negative) { "!" } else { "" },
                         imp.trait_, imp.for_));
@@ -1143,38 +1140,13 @@ impl Context {
     ///
     /// This currently isn't parallelized, but it'd be pretty easy to add
     /// parallelization to this function.
-    fn krate(mut self, mut krate: clean::Crate,
-             stability: stability_summary::ModuleSummary) -> io::Result<()> {
+    fn krate(self, mut krate: clean::Crate) -> io::Result<()> {
         let mut item = match krate.module.take() {
             Some(i) => i,
             None => return Ok(())
         };
         item.name = Some(krate.name);
 
-        // render stability dashboard
-        try!(self.recurse(stability.name.clone(), |this| {
-            let json_dst = &this.dst.join("stability.json");
-            let mut json_out = BufWriter::new(try!(File::create(json_dst)));
-            try!(write!(&mut json_out, "{}", json::as_json(&stability)));
-
-            let mut title = stability.name.clone();
-            title.push_str(" - Stability dashboard");
-            let desc = format!("API stability overview for the Rust `{}` crate.",
-                               this.layout.krate);
-            let page = layout::Page {
-                ty: "mod",
-                root_path: &this.root_path,
-                title: &title,
-                description: &desc,
-                keywords: get_basic_keywords(),
-            };
-            let html_dst = &this.dst.join("stability.html");
-            let mut html_out = BufWriter::new(try!(File::create(html_dst)));
-            layout::render(&mut html_out, &this.layout, &page,
-                           &Sidebar{ cx: this, item: &item },
-                           &stability)
-        }));
-
         // render the crate documentation
         let mut work = vec!((self, item));
         loop {
@@ -1456,21 +1428,8 @@ impl<'a> fmt::Display for Item<'a> {
         try!(write!(fmt, "<a class='{}' href=''>{}</a>",
                     shortty(self.item), self.item.name.as_ref().unwrap()));
 
-        // Write stability level
-        try!(write!(fmt, "<wbr>{}", Stability(&self.item.stability)));
-
         try!(write!(fmt, "</span>")); // in-band
-        // Links to out-of-band information, i.e. src and stability dashboard
         try!(write!(fmt, "<span class='out-of-band'>"));
-
-        // Write stability dashboard link
-        match self.item.inner {
-            clean::ModuleItem(ref m) if m.is_crate => {
-                try!(write!(fmt, "<a href='stability.html'>[stability]</a> "));
-            }
-            _ => {}
-        };
-
         try!(write!(fmt,
         r##"<span id='render-detail'>
             <a id="collapse-all" href="#">[-]</a>&nbsp;<a id="expand-all" href="#">[+]</a>
@@ -1554,11 +1513,11 @@ fn plain_summary_line(s: Option<&str>) -> String {
 }
 
 fn document(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
-    match item.doc_value() {
-        Some(s) => {
-            try!(write!(w, "<div class='docblock'>{}</div>", Markdown(s)));
-        }
-        None => {}
+    if let Some(s) = short_stability(item, true) {
+        try!(write!(w, "<div class='stability'>{}</div>", s));
+    }
+    if let Some(s) = item.doc_value() {
+        try!(write!(w, "<div class='docblock'>{}</div>", Markdown(s)));
     }
     Ok(())
 }
@@ -1593,10 +1552,17 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
     fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering {
         let ty1 = shortty(i1);
         let ty2 = shortty(i2);
-        if ty1 == ty2 {
-            return i1.name.cmp(&i2.name);
+        if ty1 != ty2 {
+            return (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2))
+        }
+        let s1 = i1.stability.as_ref().map(|s| s.level);
+        let s2 = i2.stability.as_ref().map(|s| s.level);
+        match (s1, s2) {
+            (Some(attr::Unstable), Some(attr::Stable)) => return Ordering::Greater,
+            (Some(attr::Stable), Some(attr::Unstable)) => return Ordering::Less,
+            _ => {}
         }
-        (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2))
+        i1.name.cmp(&i2.name)
     }
 
     indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
@@ -1665,19 +1631,27 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
 
             _ => {
                 if myitem.name.is_none() { continue }
+                let stab_docs = if let Some(s) = short_stability(myitem, false) {
+                    format!("[{}]", s)
+                } else {
+                    String::new()
+                };
                 try!(write!(w, "
-                    <tr>
-                        <td>{stab}<a class='{class}' href='{href}'
-                               title='{title}'>{}</a></td>
-                        <td class='docblock short'>{}</td>
+                    <tr class='{stab} module-item'>
+                        <td><a class='{class}' href='{href}'
+                               title='{title}'>{name}</a></td>
+                        <td class='docblock short'>
+                            {stab_docs} {docs}
+                        </td>
                     </tr>
                 ",
-                *myitem.name.as_ref().unwrap(),
-                Markdown(&shorter(myitem.doc_value())[..]),
+                name = *myitem.name.as_ref().unwrap(),
+                stab_docs = stab_docs,
+                docs = Markdown(&shorter(myitem.doc_value())),
                 class = shortty(myitem),
+                stab = myitem.stability_class(),
                 href = item_path(myitem),
-                title = full_path(cx, myitem),
-                stab = ConciseStability(&myitem.stability)));
+                title = full_path(cx, myitem)));
             }
         }
     }
@@ -1685,6 +1659,30 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
     write!(w, "</table>")
 }
 
+fn short_stability(item: &clean::Item, show_reason: bool) -> Option<String> {
+    item.stability.as_ref().and_then(|stab| {
+        let reason = if show_reason && stab.reason.len() > 0 {
+            format!(": {}", stab.reason)
+        } else {
+            String::new()
+        };
+        let text = if stab.deprecated_since.len() > 0 {
+            let since = if show_reason {
+                format!(" since {}", Escape(&stab.deprecated_since))
+            } else {
+                String::new()
+            };
+            format!("Deprecated{}{}", since, Markdown(&reason))
+        } else if stab.level == attr::Unstable {
+            format!("Unstable{}", Markdown(&reason))
+        } else {
+            return None
+        };
+        Some(format!("<em class='stab {}'>{}</em>",
+                     item.stability_class(), text))
+    })
+}
+
 struct Initializer<'a>(&'a str);
 
 impl<'a> fmt::Display for Initializer<'a> {
@@ -1800,10 +1798,10 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 
     fn trait_item(w: &mut fmt::Formatter, m: &clean::Item)
                   -> fmt::Result {
-        try!(write!(w, "<h3 id='{}.{}' class='method'>{}<code>",
-                    shortty(m),
-                    *m.name.as_ref().unwrap(),
-                    ConciseStability(&m.stability)));
+        try!(write!(w, "<h3 id='{ty}.{name}' class='method stab {stab}'><code>",
+                    ty = shortty(m),
+                    name = *m.name.as_ref().unwrap(),
+                    stab = m.stability_class()));
         try!(render_method(w, m, MethodLink::Anchor));
         try!(write!(w, "</code></h3>"));
         try!(document(w, m));
@@ -1854,8 +1852,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     match cache.implementors.get(&it.def_id) {
         Some(implementors) => {
             for i in implementors {
-                try!(writeln!(w, "<li>{}<code>impl{} {} for {}{}</code></li>",
-                              ConciseStability(&i.stability),
+                try!(writeln!(w, "<li><code>impl{} {} for {}{}</code></li>",
                               i.generics, i.trait_, i.for_, WhereClause(&i.generics)));
             }
         }
@@ -1964,9 +1961,10 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item,
         if fields.peek().is_some() {
             try!(write!(w, "<h2 class='fields'>Fields</h2>\n<table>"));
             for field in fields {
-                try!(write!(w, "<tr><td id='structfield.{name}'>\
-                                  {stab}<code>{name}</code></td><td>",
-                            stab = ConciseStability(&field.stability),
+                try!(write!(w, "<tr class='stab {stab}'>
+                                  <td id='structfield.{name}'>\
+                                    <code>{name}</code></td><td>",
+                            stab = field.stability_class(),
                             name = field.name.as_ref().unwrap()));
                 try!(document(w, field));
                 try!(write!(w, "</td></tr>"));
@@ -2034,8 +2032,7 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
     if !e.variants.is_empty() {
         try!(write!(w, "<h2 class='variants'>Variants</h2>\n<table>"));
         for variant in &e.variants {
-            try!(write!(w, "<tr><td id='variant.{name}'>{stab}<code>{name}</code></td><td>",
-                          stab = ConciseStability(&variant.stability),
+            try!(write!(w, "<tr><td id='variant.{name}'><code>{name}</code></td><td>",
                           name = variant.name.as_ref().unwrap()));
             try!(document(w, variant));
             match variant.inner {
@@ -2200,8 +2197,7 @@ fn render_methods(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
 
 fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink)
                -> fmt::Result {
-    try!(write!(w, "<h3 class='impl'>{}<code>impl{} ",
-                ConciseStability(&i.stability),
+    try!(write!(w, "<h3 class='impl'><code>impl{} ",
                 i.impl_.generics));
     if let Some(clean::ImplPolarity::Negative) = i.impl_.polarity {
         try!(write!(w, "!"));
@@ -2216,48 +2212,43 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink)
     }
 
     fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item,
-                    dox: bool, link: MethodLink) -> fmt::Result {
+                    link: MethodLink) -> fmt::Result {
         match item.inner {
             clean::MethodItem(..) | clean::TyMethodItem(..) => {
-                try!(write!(w, "<h4 id='method.{}' class='{}'>{}<code>",
+                try!(write!(w, "<h4 id='method.{}' class='{}'><code>",
                             *item.name.as_ref().unwrap(),
-                            shortty(item),
-                            ConciseStability(&item.stability)));
+                            shortty(item)));
                 try!(render_method(w, item, link));
                 try!(write!(w, "</code></h4>\n"));
             }
             clean::TypedefItem(ref tydef) => {
                 let name = item.name.as_ref().unwrap();
-                try!(write!(w, "<h4 id='assoc_type.{}' class='{}'>{}<code>",
+                try!(write!(w, "<h4 id='assoc_type.{}' class='{}'><code>",
                             *name,
-                            shortty(item),
-                            ConciseStability(&item.stability)));
+                            shortty(item)));
                 try!(write!(w, "type {} = {}", name, tydef.type_));
                 try!(write!(w, "</code></h4>\n"));
             }
             clean::AssociatedTypeItem(ref bounds, ref default) => {
                 let name = item.name.as_ref().unwrap();
-                try!(write!(w, "<h4 id='assoc_type.{}' class='{}'>{}<code>",
+                try!(write!(w, "<h4 id='assoc_type.{}' class='{}'><code>",
                             *name,
-                            shortty(item),
-                            ConciseStability(&item.stability)));
+                            shortty(item)));
                 try!(assoc_type(w, item, bounds, default));
                 try!(write!(w, "</code></h4>\n"));
             }
             _ => panic!("can't make docs for trait item with name {:?}", item.name)
         }
-        match item.doc_value() {
-            Some(s) if dox => {
-                try!(write!(w, "<div class='docblock'>{}</div>", Markdown(s)));
-                Ok(())
-            }
-            Some(..) | None => Ok(())
+        if let MethodLink::Anchor = link {
+            document(w, item)
+        } else {
+            Ok(())
         }
     }
 
     try!(write!(w, "<div class='impl-items'>"));
     for trait_item in i.impl_.items.iter() {
-        try!(doctraititem(w, trait_item, true, link));
+        try!(doctraititem(w, trait_item, link));
     }
 
     fn render_default_methods(w: &mut fmt::Formatter,
@@ -2271,8 +2262,7 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink)
                 None => {}
             }
 
-            try!(doctraititem(w, trait_item, false,
-                              MethodLink::GotoSource(did)));
+            try!(doctraititem(w, trait_item, MethodLink::GotoSource(did)));
         }
         Ok(())
     }
diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css
index 2af20ce59da..657b2c8fef8 100644
--- a/src/librustdoc/html/static/main.css
+++ b/src/librustdoc/html/static/main.css
@@ -245,6 +245,10 @@ nav.sub {
 .content .highlighted.tymethod { background-color: #c6afb3; }
 .content .highlighted.type { background-color: #c6afb3; }
 
+.docblock.short p {
+    display: inline;
+}
+
 .docblock.short.nowrap {
     display: block;
     overflow: hidden;
@@ -337,11 +341,16 @@ nav.sub {
 /* Shift "where ..." part of method definition down a line */
 .content .method .where { display: block; }
 /* Bit of whitespace to indent it */
-.content .method .where::before { content: '      '; }
+.content .method .where::before { content: '  '; }
 
-.content .methods .docblock { margin-left: 40px; }
+.content .methods > div { margin-left: 40px; }
 
-.content .impl-items .docblock { margin-left: 40px; }
+.content .impl-items .docblock, .content .impl-items .stability {
+    margin-left: 40px;
+}
+.content .impl-items .method, .content .impl-items .type {
+    margin-left: 20px;
+}
 
 nav {
     border-bottom: 1px solid #e0e0e0;
@@ -468,30 +477,27 @@ a {
     padding: 20px;
 }
 
-.stability {
-    border-left: 6px solid;
-    padding: 3px 6px;
-    border-radius: 3px;
+em.stab.unstable { background: #FFF5D6; border-color: #FFC600; }
+em.stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
+em.stab {
+    display: inline-block;
+    border-width: 2px;
+    border-style: solid;
+    padding: 5px;
 }
-
-h1 .stability {
-    text-transform: lowercase;
-    font-weight: 400;
-    margin-left: 14px;
-    padding: 4px 10px;
+em.stab p {
+    display: inline;
 }
 
-.impl-items .stability, .methods .stability {
-    margin-right: 20px;
+.module-item .stab {
+    border-width: 0;
+    padding: 0;
+    background: inherit !important;
 }
 
-.stability.Deprecated { border-color: #A071A8; color: #82478C; }
-.stability.Experimental { border-color: #D46D6A; color: #AA3C39; }
-.stability.Unstable { border-color: #D4B16A; color: #AA8439; }
-.stability.Stable { border-color: #54A759; color: #2D8632; }
-.stability.Frozen { border-color: #009431; color: #007726; }
-.stability.Locked { border-color: #0084B6; color: #00668c; }
-.stability.Unmarked { border-color: #BBBBBB; }
+.module-item.unstable {
+    opacity: 0.65;
+}
 
 td.summary-column {
     width: 100%;
@@ -500,11 +506,6 @@ td.summary-column {
 .summary {
     padding-right: 0px;
 }
-.summary.Deprecated { background-color: #A071A8; }
-.summary.Experimental { background-color: #D46D6A; }
-.summary.Unstable { background-color: #D4B16A; }
-.summary.Stable { background-color: #54A759; }
-.summary.Unmarked { background-color: #BBBBBB; }
 
 :target { background: #FDFFD3; }
 .line-numbers :target { background-color: transparent; }
@@ -555,9 +556,9 @@ pre.rust { position: relative; }
 .collapse-toggle {
     font-weight: 300;
     position: absolute;
-    left: 13px;
+    left: -23px;
     color: #999;
-    margin-top: 2px;
+    top: 0;
 }
 
 .toggle-wrapper > .collapse-toggle {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 008da466db0..2682bbf4662 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -91,7 +91,6 @@ pub mod html {
 pub mod markdown;
 pub mod passes;
 pub mod plugins;
-pub mod stability_summary;
 pub mod visit_ast;
 pub mod test;
 mod flock;
diff --git a/src/librustdoc/stability_summary.rs b/src/librustdoc/stability_summary.rs
deleted file mode 100644
index 3e4f6896ee6..00000000000
--- a/src/librustdoc/stability_summary.rs
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! This module crawls a `clean::Crate` and produces a summarization of the
-//! stability levels within the crate. The summary contains the module
-//! hierarchy, with item counts for every stability level per module. A parent
-//! module's count includes its children's.
-
-use std::cmp::Ordering;
-use std::ops::Add;
-
-use syntax::attr::{Unstable, Stable};
-use syntax::ast::Public;
-
-use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum};
-use clean::{ImplItem, Impl, Trait, TraitItem};
-use clean::{ExternCrateItem, ImportItem, PrimitiveItem, Stability};
-
-use html::render::cache;
-
-#[derive(RustcEncodable, RustcDecodable, PartialEq, Eq)]
-/// The counts for each stability level.
-#[derive(Copy, Clone)]
-pub struct Counts {
-    pub deprecated: u64,
-    pub unstable: u64,
-    pub stable: u64,
-
-    /// No stability level, inherited or otherwise.
-    pub unmarked: u64,
-}
-
-impl Add for Counts {
-    type Output = Counts;
-
-    fn add(self, other: Counts) -> Counts {
-        Counts {
-            deprecated:   self.deprecated   + other.deprecated,
-            unstable:     self.unstable     + other.unstable,
-            stable:       self.stable       + other.stable,
-            unmarked:     self.unmarked     + other.unmarked,
-        }
-    }
-}
-
-impl Counts {
-    fn zero() -> Counts {
-        Counts {
-            deprecated:   0,
-            unstable:     0,
-            stable:       0,
-            unmarked:     0,
-        }
-    }
-
-    pub fn total(&self) -> u64 {
-        self.deprecated + self.unstable + self.stable + self.unmarked
-    }
-}
-
-#[derive(RustcEncodable, RustcDecodable, PartialEq, Eq)]
-/// A summarized module, which includes total counts and summarized children
-/// modules.
-pub struct ModuleSummary {
-    pub name: String,
-    pub counts: Counts,
-    pub submodules: Vec<ModuleSummary>,
-}
-
-impl PartialOrd for ModuleSummary {
-    fn partial_cmp(&self, other: &ModuleSummary) -> Option<Ordering> {
-        self.name.partial_cmp(&other.name)
-    }
-}
-
-impl Ord for ModuleSummary {
-    fn cmp(&self, other: &ModuleSummary) -> Ordering {
-        self.name.cmp(&other.name)
-    }
-}
-
-// is the item considered publicly visible?
-fn visible(item: &Item) -> bool {
-    match item.inner {
-        ImplItem(_) => true,
-        _ => item.visibility == Some(Public)
-    }
-}
-
-fn count_stability(stab: Option<&Stability>) -> Counts {
-    match stab {
-        None            => Counts { unmarked: 1,     .. Counts::zero() },
-        Some(ref stab) => {
-            if !stab.deprecated_since.is_empty() {
-                return Counts { deprecated: 1, .. Counts::zero() };
-            }
-            match stab.level {
-                Unstable    => Counts { unstable: 1,     .. Counts::zero() },
-                Stable      => Counts { stable: 1,       .. Counts::zero() },
-            }
-        }
-    }
-}
-
-fn summarize_methods(item: &Item) -> Counts {
-    match cache().impls.get(&item.def_id) {
-        Some(v) => {
-            v.iter().map(|i| {
-                let count = count_stability(i.stability.as_ref());
-                if i.impl_.trait_.is_none() {
-                    count + i.impl_.items.iter()
-                        .map(|ti| summarize_item(ti).0)
-                        .fold(Counts::zero(), |acc, c| acc + c)
-                } else {
-                    count
-                }
-            }).fold(Counts::zero(), |acc, c| acc + c)
-        },
-        None => {
-            Counts::zero()
-        },
-    }
-}
-
-
-// Produce the summary for an arbitrary item. If the item is a module, include a
-// module summary. The counts for items with nested items (e.g. modules, traits,
-// impls) include all children counts.
-fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
-    let item_counts = count_stability(item.stability.as_ref()) + summarize_methods(item);
-
-    // Count this item's children, if any. Note that a trait impl is
-    // considered to have no children.
-    match item.inner {
-        // Require explicit `pub` to be visible
-        ImplItem(Impl { ref items, trait_: None, .. }) => {
-            let subcounts = items.iter().filter(|i| visible(*i))
-                                        .map(summarize_item)
-                                        .map(|s| s.0)
-                                        .fold(Counts::zero(), |acc, x| acc + x);
-            (subcounts, None)
-        }
-        // `pub` automatically
-        EnumItem(Enum { variants: ref subitems, .. }) => {
-            let subcounts = subitems.iter().map(summarize_item)
-                                           .map(|s| s.0)
-                                           .fold(Counts::zero(), |acc, x| acc + x);
-            (item_counts + subcounts, None)
-        }
-        TraitItem(Trait { ref items, .. }) => {
-            let subcounts = items.iter().map(summarize_item)
-                                        .map(|s| s.0)
-                                        .fold(Counts::zero(), |acc, x| acc + x);
-            (item_counts + subcounts, None)
-        }
-        ModuleItem(Module { ref items, .. }) => {
-            let mut counts = item_counts;
-            let mut submodules = Vec::new();
-
-            for (subcounts, submodule) in items.iter().filter(|i| visible(*i))
-                                                      .map(summarize_item) {
-                counts = counts + subcounts;
-                submodule.map(|m| submodules.push(m));
-            }
-            submodules.sort();
-
-            (counts, Some(ModuleSummary {
-                name: item.name.as_ref().map_or("".to_string(), |n| n.clone()),
-                counts: counts,
-                submodules: submodules,
-            }))
-        }
-        // no stability information for the following items:
-        ExternCrateItem(..) | ImportItem(_) |
-        PrimitiveItem(_) => (Counts::zero(), None),
-        _ => (item_counts, None)
-    }
-}
-
-/// Summarizes the stability levels in a crate.
-pub fn build(krate: &Crate) -> ModuleSummary {
-    match krate.module {
-        None => ModuleSummary {
-            name: krate.name.clone(),
-            counts: Counts::zero(),
-            submodules: Vec::new(),
-        },
-        Some(ref item) => ModuleSummary {
-            name: krate.name.clone(), .. summarize_item(item).1.unwrap()
-        }
-    }
-}