about summary refs log tree commit diff
path: root/src/librustdoc/html/format.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc/html/format.rs')
-rw-r--r--src/librustdoc/html/format.rs146
1 files changed, 69 insertions, 77 deletions
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 9c22837bdae..313734e3fdd 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -6,6 +6,7 @@
 //! them in the future to instead emit any format desired.
 
 use std::borrow::Cow;
+use std::cell::Cell;
 use std::fmt;
 
 use rustc::hir::def_id::DefId;
@@ -15,7 +16,7 @@ use rustc::hir;
 
 use crate::clean::{self, PrimitiveType};
 use crate::html::item_type::ItemType;
-use crate::html::render::{self, cache, CURRENT_LOCATION_KEY};
+use crate::html::render::{self, cache, CURRENT_DEPTH};
 
 /// Helper to render an optional visibility with a space after it (if the
 /// visibility is preset)
@@ -36,13 +37,8 @@ pub struct AsyncSpace(pub hir::IsAsync);
 /// Similar to VisSpace, but used for mutability
 #[derive(Copy, Clone)]
 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 emitting type parameter bounds.
 pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]);
-/// Wrapper struct for emitting a comma-separated list of items
-pub struct CommaSep<'a, T>(pub &'a [T]);
 pub struct AbiSpace(pub Abi);
 pub struct DefaultSpace(pub bool);
 
@@ -71,11 +67,6 @@ pub struct WhereClause<'a>{
     pub end_newline: bool,
 }
 
-pub struct HRef<'a> {
-    pub did: DefId,
-    pub text: &'a str,
-}
-
 impl<'a> VisSpace<'a> {
     pub fn get(self) -> &'a Option<clean::Visibility> {
         let VisSpace(v) = self; v
@@ -94,14 +85,14 @@ impl ConstnessSpace {
     }
 }
 
-impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        for (i, item) in self.0.iter().enumerate() {
+fn comma_sep<T: fmt::Display>(items: &[T]) -> impl fmt::Display + '_ {
+    display_fn(move |f| {
+        for (i, item) in items.iter().enumerate() {
             if i != 0 { write!(f, ", ")?; }
             fmt::Display::fmt(item, f)?;
         }
         Ok(())
-    }
+    })
 }
 
 impl<'a> fmt::Display for GenericBounds<'a> {
@@ -168,9 +159,9 @@ impl fmt::Display for clean::Generics {
             return Ok(());
         }
         if f.alternate() {
-            write!(f, "<{:#}>", CommaSep(&real_params))
+            write!(f, "<{:#}>", comma_sep(&real_params))
         } else {
-            write!(f, "&lt;{}&gt;", CommaSep(&real_params))
+            write!(f, "&lt;{}&gt;", comma_sep(&real_params))
         }
     }
 }
@@ -268,9 +259,9 @@ impl fmt::Display for clean::PolyTrait {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         if !self.generic_params.is_empty() {
             if f.alternate() {
-                write!(f, "for<{:#}> ", CommaSep(&self.generic_params))?;
+                write!(f, "for<{:#}> ", comma_sep(&self.generic_params))?;
             } else {
-                write!(f, "for&lt;{}&gt; ", CommaSep(&self.generic_params))?;
+                write!(f, "for&lt;{}&gt; ", comma_sep(&self.generic_params))?;
             }
         }
         if f.alternate() {
@@ -407,16 +398,16 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
         return None
     }
 
-    let loc = CURRENT_LOCATION_KEY.with(|l| l.borrow().clone());
+    let depth = CURRENT_DEPTH.with(|l| l.get());
     let (fqp, shortty, mut url) = match cache.paths.get(&did) {
         Some(&(ref fqp, shortty)) => {
-            (fqp, shortty, "../".repeat(loc.len()))
+            (fqp, shortty, "../".repeat(depth))
         }
         None => {
             let &(ref fqp, shortty) = cache.external_paths.get(&did)?;
             (fqp, shortty, match cache.extern_locations[&did.krate] {
                 (.., render::Remote(ref s)) => s.to_string(),
-                (.., render::Local) => "../".repeat(loc.len()),
+                (.., render::Local) => "../".repeat(depth),
                 (.., render::Unknown) => return None,
             })
         }
@@ -452,19 +443,18 @@ fn resolved_path(w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path,
         }
     }
     if w.alternate() {
-        write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.args)?;
+        write!(w, "{}{:#}", &last.name, last.args)?;
     } else {
         let path = if use_absolute {
-            match href(did) {
-                Some((_, _, fqp)) => {
-                    format!("{}::{}",
-                            fqp[..fqp.len() - 1].join("::"),
-                            HRef::new(did, fqp.last().unwrap()))
-                }
-                None => HRef::new(did, &last.name).to_string(),
+            if let Some((_, _, fqp)) = href(did) {
+                format!("{}::{}",
+                        fqp[..fqp.len() - 1].join("::"),
+                        anchor(did, fqp.last().unwrap()))
+            } else {
+                last.name.to_string()
             }
         } else {
-            HRef::new(did, &last.name).to_string()
+            anchor(did, &last.name).to_string()
         };
         write!(w, "{}{}", path, last.args)?;
     }
@@ -479,7 +469,7 @@ fn primitive_link(f: &mut fmt::Formatter<'_>,
     if !f.alternate() {
         match m.primitive_locations.get(&prim) {
             Some(&def_id) if def_id.is_local() => {
-                let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
+                let len = CURRENT_DEPTH.with(|s| s.get());
                 let len = if len == 0 {0} else {len - 1};
                 write!(f, "<a class=\"primitive\" href=\"{}primitive.{}.html\">",
                        "../".repeat(len),
@@ -492,7 +482,7 @@ fn primitive_link(f: &mut fmt::Formatter<'_>,
                         Some((cname, s.to_string()))
                     }
                     (ref cname, _, render::Local) => {
-                        let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
+                        let len = CURRENT_DEPTH.with(|s| s.get());
                         Some((cname, "../".repeat(len)))
                     }
                     (.., render::Unknown) => None,
@@ -516,38 +506,30 @@ fn primitive_link(f: &mut fmt::Formatter<'_>,
 }
 
 /// Helper to render type parameters
-fn tybounds(w: &mut fmt::Formatter<'_>,
-            param_names: &Option<Vec<clean::GenericBound>>) -> fmt::Result {
-    match *param_names {
-        Some(ref params) => {
-            for param in params {
-                write!(w, " + ")?;
-                fmt::Display::fmt(param, w)?;
+fn tybounds(param_names: &Option<Vec<clean::GenericBound>>) -> impl fmt::Display + '_ {
+    display_fn(move |f| {
+        match *param_names {
+            Some(ref params) => {
+                for param in params {
+                    write!(f, " + ")?;
+                    fmt::Display::fmt(param, f)?;
+                }
+                Ok(())
             }
-            Ok(())
+            None => Ok(())
         }
-        None => Ok(())
-    }
-}
-
-impl<'a> HRef<'a> {
-    pub fn new(did: DefId, text: &'a str) -> HRef<'a> {
-        HRef { did: did, text: text }
-    }
+    })
 }
 
-impl<'a> fmt::Display for HRef<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match href(self.did) {
-            Some((url, shortty, fqp)) => if !f.alternate() {
-                write!(f, "<a class=\"{}\" href=\"{}\" title=\"{} {}\">{}</a>",
-                       shortty, url, shortty, fqp.join("::"), self.text)
-            } else {
-                write!(f, "{}", self.text)
-            },
-            _ => write!(f, "{}", self.text),
+pub fn anchor(did: DefId, text: &str) -> impl fmt::Display + '_ {
+    display_fn(move |f| {
+        if let Some((url, short_ty, fqp)) = href(did) {
+            write!(f, r#"<a class="{}" href="{}" title="{} {}">{}</a>"#,
+                short_ty, url, short_ty, fqp.join("::"), text)
+        } else {
+            write!(f, "{}", text)
         }
-    }
+    })
 }
 
 fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> fmt::Result {
@@ -561,7 +543,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
             }
             // Paths like `T::Output` and `Self::Output` should be rendered with all segments.
             resolved_path(f, did, path, is_generic, use_absolute)?;
-            tybounds(f, param_names)
+            fmt::Display::fmt(&tybounds(param_names), f)
         }
         clean::Infer => write!(f, "_"),
         clean::Primitive(prim) => primitive_link(f, prim, prim.as_str()),
@@ -570,12 +552,12 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
                 write!(f, "{}{:#}fn{:#}{:#}",
                        UnsafetySpace(decl.unsafety),
                        AbiSpace(decl.abi),
-                       CommaSep(&decl.generic_params),
+                       comma_sep(&decl.generic_params),
                        decl.decl)
             } else {
                 write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?;
                 primitive_link(f, PrimitiveType::Fn, "fn")?;
-                write!(f, "{}{}", CommaSep(&decl.generic_params), decl.decl)
+                write!(f, "{}{}", comma_sep(&decl.generic_params), decl.decl)
             }
         }
         clean::Tuple(ref typs) => {
@@ -589,7 +571,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
                 }
                 many => {
                     primitive_link(f, PrimitiveType::Tuple, "(")?;
-                    fmt::Display::fmt(&CommaSep(many), f)?;
+                    fmt::Display::fmt(&comma_sep(many), f)?;
                     primitive_link(f, PrimitiveType::Tuple, ")")
                 }
             }
@@ -607,19 +589,22 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) ->
         clean::Never => primitive_link(f, PrimitiveType::Never, "!"),
         clean::CVarArgs => primitive_link(f, PrimitiveType::CVarArgs, "..."),
         clean::RawPointer(m, ref t) => {
+            let m = match m {
+                clean::Immutable => "const",
+                clean::Mutable => "mut",
+            };
             match **t {
                 clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {
                     if f.alternate() {
                         primitive_link(f, clean::PrimitiveType::RawPointer,
-                                       &format!("*{}{:#}", RawMutableSpace(m), t))
+                                       &format!("*{} {:#}", m, t))
                     } else {
                         primitive_link(f, clean::PrimitiveType::RawPointer,
-                                       &format!("*{}{}", RawMutableSpace(m), t))
+                                       &format!("*{} {}", m, t))
                     }
                 }
                 _ => {
-                    primitive_link(f, clean::PrimitiveType::RawPointer,
-                                   &format!("*{}", RawMutableSpace(m)))?;
+                    primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m))?;
                     fmt::Display::fmt(t, f)
                 }
             }
@@ -1047,15 +1032,6 @@ impl fmt::Display for MutableSpace {
     }
 }
 
-impl fmt::Display for RawMutableSpace {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match *self {
-            RawMutableSpace(clean::Immutable) => write!(f, "const "),
-            RawMutableSpace(clean::Mutable) => write!(f, "mut "),
-        }
-    }
-}
-
 impl fmt::Display for AbiSpace {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let quot = if f.alternate() { "\"" } else { "&quot;" };
@@ -1075,3 +1051,19 @@ impl fmt::Display for DefaultSpace {
         }
     }
 }
+
+crate fn display_fn(
+    f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+) -> impl fmt::Display {
+    WithFormatter(Cell::new(Some(f)))
+}
+
+struct WithFormatter<F>(Cell<Option<F>>);
+
+impl<F> fmt::Display for WithFormatter<F>
+    where F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        (self.0.take()).unwrap()(f)
+    }
+}