diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 29eb67f023f0b..c53482e264586 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -2292,14 +2292,16 @@ impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
             if matchers.len() <= 1 {
                 format!(
                     "{}macro {}{} {{\n    ...\n}}",
-                    vis.print_with_space(cx.tcx, def_id, &cx.cache),
+                    // FIXME(camelid): this might create broken links!
+                    vis.print_with_space(cx.tcx, def_id, &cx.cache, 0),
                     name,
                     matchers.iter().map(|span| span.to_src(cx)).collect::<String>(),
                 )
             } else {
                 format!(
                     "{}macro {} {{\n{}}}",
-                    vis.print_with_space(cx.tcx, def_id, &cx.cache),
+                    // FIXME(camelid): this might create broken links!
+                    vis.print_with_space(cx.tcx, def_id, &cx.cache, 0),
                     name,
                     matchers
                         .iter()
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index e560843383ec5..eae73bd16260f 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -190,8 +190,8 @@ impl Item {
         self.attrs.collapsed_doc_value()
     }
 
-    crate fn links(&self, cache: &Cache) -> Vec<RenderedLink> {
-        self.attrs.links(self.def_id.krate, cache)
+    crate fn links(&self, cache: &Cache, depth: usize) -> Vec<RenderedLink> {
+        self.attrs.links(self.def_id.krate, cache, depth)
     }
 
     crate fn is_crate(&self) -> bool {
@@ -847,16 +847,15 @@ impl Attributes {
     /// Gets links as a vector
     ///
     /// Cache must be populated before call
-    crate fn links(&self, krate: CrateNum, cache: &Cache) -> Vec<RenderedLink> {
+    crate fn links(&self, krate: CrateNum, cache: &Cache, depth: usize) -> Vec<RenderedLink> {
         use crate::html::format::href;
-        use crate::html::render::CURRENT_DEPTH;
 
         self.links
             .iter()
             .filter_map(|ItemLink { link: s, link_text, did, fragment }| {
                 match *did {
                     Some(did) => {
-                        if let Some((mut href, ..)) = href(did, cache) {
+                        if let Some((mut href, ..)) = href(did, cache, depth) {
                             if let Some(ref fragment) = *fragment {
                                 href.push('#');
                                 href.push_str(fragment);
@@ -873,10 +872,7 @@ impl Attributes {
                     None => {
                         if let Some(ref fragment) = *fragment {
                             let url = match cache.extern_locations.get(&krate) {
-                                Some(&(_, _, ExternalLocation::Local)) => {
-                                    let depth = CURRENT_DEPTH.with(|l| l.get());
-                                    "../".repeat(depth)
-                                }
+                                Some(&(_, _, ExternalLocation::Local)) => "../".repeat(depth),
                                 Some(&(_, _, ExternalLocation::Remote(ref s))) => s.to_string(),
                                 Some(&(_, _, ExternalLocation::Unknown)) | None => String::from(
                                     // NOTE: intentionally doesn't pass crate name to avoid having
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index a64e8c21c462e..73abab26e7696 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -414,7 +414,10 @@ crate fn resolve_type(cx: &mut DocContext<'_>, path: Path, id: hir::HirId) -> Ty
             return Generic(kw::SelfUpper);
         }
         Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => {
-            return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache))));
+            // FIXME(camelid): I hope passing 0 as the depth doesn't break anything....
+            //                 Then again, I think used to be 0 anyway through CURRENT_DEPTH
+            //                 because (I think) rendering hadn't started yet.
+            return Generic(Symbol::intern(&format!("{:#}", path.print(&cx.cache, 0))));
         }
         Res::SelfTy(..) | Res::Def(DefKind::TyParam | DefKind::AssocTy, _) => true,
         _ => false,
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index bea0e75832c33..2ccc4479e4ea9 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -20,7 +20,6 @@ use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::html::escape::Escape;
 use crate::html::render::cache::ExternalLocation;
-use crate::html::render::CURRENT_DEPTH;
 
 crate trait Print {
     fn print(self, buffer: &mut Buffer);
@@ -147,24 +146,27 @@ fn comma_sep<T: fmt::Display>(items: impl Iterator<Item = T>) -> impl fmt::Displ
 crate fn print_generic_bounds<'a>(
     bounds: &'a [clean::GenericBound],
     cache: &'a Cache,
+    depth: usize,
 ) -> impl fmt::Display + 'a {
     display_fn(move |f| {
         let mut bounds_dup = FxHashSet::default();
 
-        for (i, bound) in
-            bounds.iter().filter(|b| bounds_dup.insert(b.print(cache).to_string())).enumerate()
+        for (i, bound) in bounds
+            .iter()
+            .filter(|b| bounds_dup.insert(b.print(cache, depth).to_string()))
+            .enumerate()
         {
             if i > 0 {
                 f.write_str(" + ")?;
             }
-            fmt::Display::fmt(&bound.print(cache), f)?;
+            fmt::Display::fmt(&bound.print(cache, depth), f)?;
         }
         Ok(())
     })
 }
 
 impl clean::GenericParamDef {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| match self.kind {
             clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name),
             clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => {
@@ -172,17 +174,17 @@ impl clean::GenericParamDef {
 
                 if !bounds.is_empty() {
                     if f.alternate() {
-                        write!(f, ": {:#}", print_generic_bounds(bounds, cache))?;
+                        write!(f, ": {:#}", print_generic_bounds(bounds, cache, depth))?;
                     } else {
-                        write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache))?;
+                        write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache, depth))?;
                     }
                 }
 
                 if let Some(ref ty) = default {
                     if f.alternate() {
-                        write!(f, " = {:#}", ty.print(cache))?;
+                        write!(f, " = {:#}", ty.print(cache, depth))?;
                     } else {
-                        write!(f, "&nbsp;=&nbsp;{}", ty.print(cache))?;
+                        write!(f, "&nbsp;=&nbsp;{}", ty.print(cache, depth))?;
                     }
                 }
 
@@ -190,9 +192,9 @@ impl clean::GenericParamDef {
             }
             clean::GenericParamDefKind::Const { ref ty, .. } => {
                 if f.alternate() {
-                    write!(f, "const {}: {:#}", self.name, ty.print(cache))
+                    write!(f, "const {}: {:#}", self.name, ty.print(cache, depth))
                 } else {
-                    write!(f, "const {}:&nbsp;{}", self.name, ty.print(cache))
+                    write!(f, "const {}:&nbsp;{}", self.name, ty.print(cache, depth))
                 }
             }
         })
@@ -200,7 +202,7 @@ impl clean::GenericParamDef {
 }
 
 impl clean::Generics {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| {
             let real_params =
                 self.params.iter().filter(|p| !p.is_synthetic_type_param()).collect::<Vec<_>>();
@@ -208,16 +210,20 @@ impl clean::Generics {
                 return Ok(());
             }
             if f.alternate() {
-                write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print(cache))))
+                write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print(cache, depth))))
             } else {
-                write!(f, "&lt;{}&gt;", comma_sep(real_params.iter().map(|g| g.print(cache))))
+                write!(
+                    f,
+                    "&lt;{}&gt;",
+                    comma_sep(real_params.iter().map(|g| g.print(cache, depth)))
+                )
             }
         })
     }
 }
 
 impl<'a> WhereClause<'a> {
-    crate fn print<'b>(&'b self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b>(&'b self, cache: &'b Cache, depth: usize) -> impl fmt::Display + 'b {
         display_fn(move |f| {
             let &WhereClause { gens, indent, end_newline } = self;
             if gens.where_predicates.is_empty() {
@@ -246,14 +252,14 @@ impl<'a> WhereClause<'a> {
                         if f.alternate() {
                             clause.push_str(&format!(
                                 "{:#}: {:#}",
-                                ty.print(cache),
-                                print_generic_bounds(bounds, cache)
+                                ty.print(cache, depth),
+                                print_generic_bounds(bounds, cache, depth)
                             ));
                         } else {
                             clause.push_str(&format!(
                                 "{}: {}",
-                                ty.print(cache),
-                                print_generic_bounds(bounds, cache)
+                                ty.print(cache, depth),
+                                print_generic_bounds(bounds, cache, depth)
                             ));
                         }
                     }
@@ -263,7 +269,7 @@ impl<'a> WhereClause<'a> {
                             lifetime.print(),
                             bounds
                                 .iter()
-                                .map(|b| b.print(cache).to_string())
+                                .map(|b| b.print(cache, depth).to_string())
                                 .collect::<Vec<_>>()
                                 .join(" + ")
                         ));
@@ -272,14 +278,14 @@ impl<'a> WhereClause<'a> {
                         if f.alternate() {
                             clause.push_str(&format!(
                                 "{:#} == {:#}",
-                                lhs.print(cache),
-                                rhs.print(cache)
+                                lhs.print(cache, depth),
+                                rhs.print(cache, depth)
                             ));
                         } else {
                             clause.push_str(&format!(
                                 "{} == {}",
-                                lhs.print(cache),
-                                rhs.print(cache)
+                                lhs.print(cache, depth),
+                                rhs.print(cache, depth)
                             ));
                         }
                     }
@@ -332,34 +338,34 @@ impl clean::Constant {
 }
 
 impl clean::PolyTrait {
-    fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| {
             if !self.generic_params.is_empty() {
                 if f.alternate() {
                     write!(
                         f,
                         "for<{:#}> ",
-                        comma_sep(self.generic_params.iter().map(|g| g.print(cache)))
+                        comma_sep(self.generic_params.iter().map(|g| g.print(cache, depth)))
                     )?;
                 } else {
                     write!(
                         f,
                         "for&lt;{}&gt; ",
-                        comma_sep(self.generic_params.iter().map(|g| g.print(cache)))
+                        comma_sep(self.generic_params.iter().map(|g| g.print(cache, depth)))
                     )?;
                 }
             }
             if f.alternate() {
-                write!(f, "{:#}", self.trait_.print(cache))
+                write!(f, "{:#}", self.trait_.print(cache, depth))
             } else {
-                write!(f, "{}", self.trait_.print(cache))
+                write!(f, "{}", self.trait_.print(cache, depth))
             }
         })
     }
 }
 
 impl clean::GenericBound {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| match self {
             clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
             clean::GenericBound::TraitBound(ty, modifier) => {
@@ -369,9 +375,9 @@ impl clean::GenericBound {
                     hir::TraitBoundModifier::MaybeConst => "?const",
                 };
                 if f.alternate() {
-                    write!(f, "{}{:#}", modifier_str, ty.print(cache))
+                    write!(f, "{}{:#}", modifier_str, ty.print(cache, depth))
                 } else {
-                    write!(f, "{}{}", modifier_str, ty.print(cache))
+                    write!(f, "{}{}", modifier_str, ty.print(cache, depth))
                 }
             }
         })
@@ -379,7 +385,7 @@ impl clean::GenericBound {
 }
 
 impl clean::GenericArgs {
-    fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| {
             match self {
                 clean::GenericArgs::AngleBracketed { args, bindings } => {
@@ -396,9 +402,9 @@ impl clean::GenericArgs {
                             }
                             comma = true;
                             if f.alternate() {
-                                write!(f, "{:#}", arg.print(cache))?;
+                                write!(f, "{:#}", arg.print(cache, depth))?;
                             } else {
-                                write!(f, "{}", arg.print(cache))?;
+                                write!(f, "{}", arg.print(cache, depth))?;
                             }
                         }
                         for binding in bindings {
@@ -407,9 +413,9 @@ impl clean::GenericArgs {
                             }
                             comma = true;
                             if f.alternate() {
-                                write!(f, "{:#}", binding.print(cache))?;
+                                write!(f, "{:#}", binding.print(cache, depth))?;
                             } else {
-                                write!(f, "{}", binding.print(cache))?;
+                                write!(f, "{}", binding.print(cache, depth))?;
                             }
                         }
                         if f.alternate() {
@@ -428,17 +434,17 @@ impl clean::GenericArgs {
                         }
                         comma = true;
                         if f.alternate() {
-                            write!(f, "{:#}", ty.print(cache))?;
+                            write!(f, "{:#}", ty.print(cache, depth))?;
                         } else {
-                            write!(f, "{}", ty.print(cache))?;
+                            write!(f, "{}", ty.print(cache, depth))?;
                         }
                     }
                     f.write_str(")")?;
                     if let Some(ref ty) = *output {
                         if f.alternate() {
-                            write!(f, " -> {:#}", ty.print(cache))?;
+                            write!(f, " -> {:#}", ty.print(cache, depth))?;
                         } else {
-                            write!(f, " -&gt; {}", ty.print(cache))?;
+                            write!(f, " -&gt; {}", ty.print(cache, depth))?;
                         }
                     }
                 }
@@ -449,19 +455,19 @@ impl clean::GenericArgs {
 }
 
 impl clean::PathSegment {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| {
             if f.alternate() {
-                write!(f, "{}{:#}", self.name, self.args.print(cache))
+                write!(f, "{}{:#}", self.name, self.args.print(cache, depth))
             } else {
-                write!(f, "{}{}", self.name, self.args.print(cache))
+                write!(f, "{}{}", self.name, self.args.print(cache, depth))
             }
         })
     }
 }
 
 impl clean::Path {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| {
             if self.global {
                 f.write_str("::")?
@@ -472,9 +478,9 @@ impl clean::Path {
                     f.write_str("::")?
                 }
                 if f.alternate() {
-                    write!(f, "{:#}", seg.print(cache))?;
+                    write!(f, "{:#}", seg.print(cache, depth))?;
                 } else {
-                    write!(f, "{}", seg.print(cache))?;
+                    write!(f, "{}", seg.print(cache, depth))?;
                 }
             }
             Ok(())
@@ -482,12 +488,11 @@ impl clean::Path {
     }
 }
 
-crate fn href(did: DefId, cache: &Cache) -> Option<(String, ItemType, Vec<String>)> {
+crate fn href(did: DefId, cache: &Cache, depth: usize) -> Option<(String, ItemType, Vec<String>)> {
     if !did.is_local() && !cache.access_levels.is_public(did) && !cache.document_private {
         return None;
     }
 
-    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(depth)),
         None => {
@@ -531,6 +536,7 @@ fn resolved_path(
     print_all: bool,
     use_absolute: bool,
     cache: &Cache,
+    depth: usize,
 ) -> fmt::Result {
     let last = path.segments.last().unwrap();
 
@@ -540,22 +546,22 @@ fn resolved_path(
         }
     }
     if w.alternate() {
-        write!(w, "{}{:#}", &last.name, last.args.print(cache))?;
+        write!(w, "{}{:#}", &last.name, last.args.print(cache, depth))?;
     } else {
         let path = if use_absolute {
-            if let Some((_, _, fqp)) = href(did, cache) {
+            if let Some((_, _, fqp)) = href(did, cache, depth) {
                 format!(
                     "{}::{}",
                     fqp[..fqp.len() - 1].join("::"),
-                    anchor(did, fqp.last().unwrap(), cache)
+                    anchor(did, fqp.last().unwrap(), cache, depth)
                 )
             } else {
                 last.name.to_string()
             }
         } else {
-            anchor(did, &*last.name.as_str(), cache).to_string()
+            anchor(did, &*last.name.as_str(), cache, depth).to_string()
         };
-        write!(w, "{}{}", path, last.args.print(cache))?;
+        write!(w, "{}{}", path, last.args.print(cache, depth))?;
     }
     Ok(())
 }
@@ -565,13 +571,13 @@ fn primitive_link(
     prim: clean::PrimitiveType,
     name: &str,
     m: &Cache,
+    depth: usize,
 ) -> fmt::Result {
     let mut needs_termination = false;
     if !f.alternate() {
         match m.primitive_locations.get(&prim) {
             Some(&def_id) if def_id.is_local() => {
-                let len = CURRENT_DEPTH.with(|s| s.get());
-                let len = if len == 0 { 0 } else { len - 1 };
+                let len = if depth == 0 { 0 } else { depth - 1 };
                 write!(
                     f,
                     "<a class=\"primitive\" href=\"{}primitive.{}.html\">",
@@ -583,10 +589,7 @@ fn primitive_link(
             Some(&def_id) => {
                 let loc = match m.extern_locations[&def_id.krate] {
                     (ref cname, _, ExternalLocation::Remote(ref s)) => Some((cname, s.to_string())),
-                    (ref cname, _, ExternalLocation::Local) => {
-                        let len = CURRENT_DEPTH.with(|s| s.get());
-                        Some((cname, "../".repeat(len)))
-                    }
+                    (ref cname, _, ExternalLocation::Local) => Some((cname, "../".repeat(depth))),
                     (.., ExternalLocation::Unknown) => None,
                 };
                 if let Some((cname, root)) = loc {
@@ -614,12 +617,13 @@ fn primitive_link(
 fn tybounds<'a>(
     param_names: &'a Option<Vec<clean::GenericBound>>,
     cache: &'a Cache,
+    depth: usize,
 ) -> impl fmt::Display + 'a {
     display_fn(move |f| match *param_names {
         Some(ref params) => {
             for param in params {
                 write!(f, " + ")?;
-                fmt::Display::fmt(&param.print(cache), f)?;
+                fmt::Display::fmt(&param.print(cache, depth), f)?;
             }
             Ok(())
         }
@@ -627,9 +631,14 @@ fn tybounds<'a>(
     })
 }
 
-crate fn anchor<'a>(did: DefId, text: &'a str, cache: &'a Cache) -> impl fmt::Display + 'a {
+crate fn anchor<'a>(
+    did: DefId,
+    text: &'a str,
+    cache: &'a Cache,
+    depth: usize,
+) -> impl fmt::Display + 'a {
     display_fn(move |f| {
-        if let Some((url, short_ty, fqp)) = href(did, cache) {
+        if let Some((url, short_ty, fqp)) = href(did, cache, depth) {
             write!(
                 f,
                 r#"<a class="{}" href="{}" title="{} {}">{}</a>"#,
@@ -650,6 +659,7 @@ fn fmt_type(
     f: &mut fmt::Formatter<'_>,
     use_absolute: bool,
     cache: &Cache,
+    depth: usize,
 ) -> fmt::Result {
     debug!("fmt_type(t = {:?})", t);
 
@@ -660,69 +670,69 @@ fn fmt_type(
                 f.write_str("dyn ")?;
             }
             // Paths like `T::Output` and `Self::Output` should be rendered with all segments.
-            resolved_path(f, did, path, is_generic, use_absolute, cache)?;
-            fmt::Display::fmt(&tybounds(param_names, cache), f)
+            resolved_path(f, did, path, is_generic, use_absolute, cache, depth)?;
+            fmt::Display::fmt(&tybounds(param_names, cache, depth), f)
         }
         clean::Infer => write!(f, "_"),
-        clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cache),
+        clean::Primitive(prim) => primitive_link(f, prim, prim.as_str(), cache, depth),
         clean::BareFunction(ref decl) => {
             if f.alternate() {
                 write!(
                     f,
                     "{:#}{}{:#}fn{:#}",
-                    decl.print_hrtb_with_space(cache),
+                    decl.print_hrtb_with_space(cache, depth),
                     decl.unsafety.print_with_space(),
                     print_abi_with_space(decl.abi),
-                    decl.decl.print(cache)
+                    decl.decl.print(cache, depth)
                 )
             } else {
                 write!(
                     f,
                     "{}{}{}",
-                    decl.print_hrtb_with_space(cache),
+                    decl.print_hrtb_with_space(cache, depth),
                     decl.unsafety.print_with_space(),
                     print_abi_with_space(decl.abi)
                 )?;
-                primitive_link(f, PrimitiveType::Fn, "fn", cache)?;
-                write!(f, "{}", decl.decl.print(cache))
+                primitive_link(f, PrimitiveType::Fn, "fn", cache, depth)?;
+                write!(f, "{}", decl.decl.print(cache, depth))
             }
         }
         clean::Tuple(ref typs) => {
             match &typs[..] {
-                &[] => primitive_link(f, PrimitiveType::Unit, "()", cache),
+                &[] => primitive_link(f, PrimitiveType::Unit, "()", cache, depth),
                 &[ref one] => {
-                    primitive_link(f, PrimitiveType::Tuple, "(", cache)?;
+                    primitive_link(f, PrimitiveType::Tuple, "(", cache, depth)?;
                     // Carry `f.alternate()` into this display w/o branching manually.
-                    fmt::Display::fmt(&one.print(cache), f)?;
-                    primitive_link(f, PrimitiveType::Tuple, ",)", cache)
+                    fmt::Display::fmt(&one.print(cache, depth), f)?;
+                    primitive_link(f, PrimitiveType::Tuple, ",)", cache, depth)
                 }
                 many => {
-                    primitive_link(f, PrimitiveType::Tuple, "(", cache)?;
+                    primitive_link(f, PrimitiveType::Tuple, "(", cache, depth)?;
                     for (i, item) in many.iter().enumerate() {
                         if i != 0 {
                             write!(f, ", ")?;
                         }
-                        fmt::Display::fmt(&item.print(cache), f)?;
+                        fmt::Display::fmt(&item.print(cache, depth), f)?;
                     }
-                    primitive_link(f, PrimitiveType::Tuple, ")", cache)
+                    primitive_link(f, PrimitiveType::Tuple, ")", cache, depth)
                 }
             }
         }
         clean::Slice(ref t) => {
-            primitive_link(f, PrimitiveType::Slice, "[", cache)?;
-            fmt::Display::fmt(&t.print(cache), f)?;
-            primitive_link(f, PrimitiveType::Slice, "]", cache)
+            primitive_link(f, PrimitiveType::Slice, "[", cache, depth)?;
+            fmt::Display::fmt(&t.print(cache, depth), f)?;
+            primitive_link(f, PrimitiveType::Slice, "]", cache, depth)
         }
         clean::Array(ref t, ref n) => {
-            primitive_link(f, PrimitiveType::Array, "[", cache)?;
-            fmt::Display::fmt(&t.print(cache), f)?;
+            primitive_link(f, PrimitiveType::Array, "[", cache, depth)?;
+            fmt::Display::fmt(&t.print(cache, depth), f)?;
             if f.alternate() {
-                primitive_link(f, PrimitiveType::Array, &format!("; {}]", n), cache)
+                primitive_link(f, PrimitiveType::Array, &format!("; {}]", n), cache, depth)
             } else {
-                primitive_link(f, PrimitiveType::Array, &format!("; {}]", Escape(n)), cache)
+                primitive_link(f, PrimitiveType::Array, &format!("; {}]", Escape(n)), cache, depth)
             }
         }
-        clean::Never => primitive_link(f, PrimitiveType::Never, "!", cache),
+        clean::Never => primitive_link(f, PrimitiveType::Never, "!", cache, depth),
         clean::RawPointer(m, ref t) => {
             let m = match m {
                 hir::Mutability::Mut => "mut",
@@ -734,15 +744,17 @@ fn fmt_type(
                         primitive_link(
                             f,
                             clean::PrimitiveType::RawPointer,
-                            &format!("*{} {:#}", m, t.print(cache)),
+                            &format!("*{} {:#}", m, t.print(cache, depth)),
                             cache,
+                            depth,
                         )
                     } else {
                         primitive_link(
                             f,
                             clean::PrimitiveType::RawPointer,
-                            &format!("*{} {}", m, t.print(cache)),
+                            &format!("*{} {}", m, t.print(cache, depth)),
                             cache,
+                            depth,
                         )
                     }
                 }
@@ -752,8 +764,9 @@ fn fmt_type(
                         clean::PrimitiveType::RawPointer,
                         &format!("*{} ", m),
                         cache,
+                        depth,
                     )?;
-                    fmt::Display::fmt(&t.print(cache), f)
+                    fmt::Display::fmt(&t.print(cache, depth), f)
                 }
             }
         }
@@ -773,15 +786,17 @@ fn fmt_type(
                                 primitive_link(
                                     f,
                                     PrimitiveType::Slice,
-                                    &format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cache)),
+                                    &format!("{}{}{}[{:#}]", amp, lt, m, bt.print(cache, depth)),
                                     cache,
+                                    depth,
                                 )
                             } else {
                                 primitive_link(
                                     f,
                                     PrimitiveType::Slice,
-                                    &format!("{}{}{}[{}]", amp, lt, m, bt.print(cache)),
+                                    &format!("{}{}{}[{}]", amp, lt, m, bt.print(cache, depth)),
                                     cache,
+                                    depth,
                                 )
                             }
                         }
@@ -791,19 +806,20 @@ fn fmt_type(
                                 PrimitiveType::Slice,
                                 &format!("{}{}{}[", amp, lt, m),
                                 cache,
+                                depth,
                             )?;
                             if f.alternate() {
-                                write!(f, "{:#}", bt.print(cache))?;
+                                write!(f, "{:#}", bt.print(cache, depth))?;
                             } else {
-                                write!(f, "{}", bt.print(cache))?;
+                                write!(f, "{}", bt.print(cache, depth))?;
                             }
-                            primitive_link(f, PrimitiveType::Slice, "]", cache)
+                            primitive_link(f, PrimitiveType::Slice, "]", cache, depth)
                         }
                     }
                 }
                 clean::ResolvedPath { param_names: Some(ref v), .. } if !v.is_empty() => {
                     write!(f, "{}{}{}(", amp, lt, m)?;
-                    fmt_type(&ty, f, use_absolute, cache)?;
+                    fmt_type(&ty, f, use_absolute, cache, depth)?;
                     write!(f, ")")
                 }
                 clean::Generic(..) => {
@@ -812,20 +828,21 @@ fn fmt_type(
                         PrimitiveType::Reference,
                         &format!("{}{}{}", amp, lt, m),
                         cache,
+                        depth,
                     )?;
-                    fmt_type(&ty, f, use_absolute, cache)
+                    fmt_type(&ty, f, use_absolute, cache, depth)
                 }
                 _ => {
                     write!(f, "{}{}{}", amp, lt, m)?;
-                    fmt_type(&ty, f, use_absolute, cache)
+                    fmt_type(&ty, f, use_absolute, cache, depth)
                 }
             }
         }
         clean::ImplTrait(ref bounds) => {
             if f.alternate() {
-                write!(f, "impl {:#}", print_generic_bounds(bounds, cache))
+                write!(f, "impl {:#}", print_generic_bounds(bounds, cache, depth))
             } else {
-                write!(f, "impl {}", print_generic_bounds(bounds, cache))
+                write!(f, "impl {}", print_generic_bounds(bounds, cache, depth))
             }
         }
         clean::QPath { ref name, ref self_type, ref trait_ } => {
@@ -837,15 +854,25 @@ fn fmt_type(
             };
             if f.alternate() {
                 if should_show_cast {
-                    write!(f, "<{:#} as {:#}>::", self_type.print(cache), trait_.print(cache))?
+                    write!(
+                        f,
+                        "<{:#} as {:#}>::",
+                        self_type.print(cache, depth),
+                        trait_.print(cache, depth)
+                    )?
                 } else {
-                    write!(f, "{:#}::", self_type.print(cache))?
+                    write!(f, "{:#}::", self_type.print(cache, depth))?
                 }
             } else {
                 if should_show_cast {
-                    write!(f, "&lt;{} as {}&gt;::", self_type.print(cache), trait_.print(cache))?
+                    write!(
+                        f,
+                        "&lt;{} as {}&gt;::",
+                        self_type.print(cache, depth),
+                        trait_.print(cache, depth)
+                    )?
                 } else {
-                    write!(f, "{}::", self_type.print(cache))?
+                    write!(f, "{}::", self_type.print(cache, depth))?
                 }
             };
             match *trait_ {
@@ -860,7 +887,7 @@ fn fmt_type(
                 //        everything comes in as a fully resolved QPath (hard to
                 //        look at).
                 box clean::ResolvedPath { did, ref param_names, .. } => {
-                    match href(did, cache) {
+                    match href(did, cache, depth) {
                         Some((ref url, _, ref path)) if !f.alternate() => {
                             write!(
                                 f,
@@ -886,52 +913,57 @@ fn fmt_type(
 }
 
 impl clean::Type {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
-        display_fn(move |f| fmt_type(self, f, false, cache))
+    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache, depth: usize) -> impl fmt::Display + 'b {
+        display_fn(move |f| fmt_type(self, f, false, cache, depth))
     }
 }
 
 impl clean::Impl {
-    crate fn print<'a>(&'a self, cache: &'a Cache, use_absolute: bool) -> impl fmt::Display + 'a {
+    crate fn print<'a>(
+        &'a self,
+        cache: &'a Cache,
+        use_absolute: bool,
+        depth: usize,
+    ) -> impl fmt::Display + 'a {
         display_fn(move |f| {
             if f.alternate() {
-                write!(f, "impl{:#} ", self.generics.print(cache))?;
+                write!(f, "impl{:#} ", self.generics.print(cache, depth))?;
             } else {
-                write!(f, "impl{} ", self.generics.print(cache))?;
+                write!(f, "impl{} ", self.generics.print(cache, depth))?;
             }
 
             if let Some(ref ty) = self.trait_ {
                 if self.negative_polarity {
                     write!(f, "!")?;
                 }
-                fmt::Display::fmt(&ty.print(cache), f)?;
+                fmt::Display::fmt(&ty.print(cache, depth), f)?;
                 write!(f, " for ")?;
             }
 
             if let Some(ref ty) = self.blanket_impl {
-                fmt_type(ty, f, use_absolute, cache)?;
+                fmt_type(ty, f, use_absolute, cache, depth)?;
             } else {
-                fmt_type(&self.for_, f, use_absolute, cache)?;
+                fmt_type(&self.for_, f, use_absolute, cache, depth)?;
             }
 
             let where_clause = WhereClause { gens: &self.generics, indent: 0, end_newline: true };
-            fmt::Display::fmt(&where_clause.print(cache), f)?;
+            fmt::Display::fmt(&where_clause.print(cache, depth), f)?;
             Ok(())
         })
     }
 }
 
 impl clean::Arguments {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| {
             for (i, input) in self.values.iter().enumerate() {
                 if !input.name.is_empty() {
                     write!(f, "{}: ", input.name)?;
                 }
                 if f.alternate() {
-                    write!(f, "{:#}", input.type_.print(cache))?;
+                    write!(f, "{:#}", input.type_.print(cache, depth))?;
                 } else {
-                    write!(f, "{}", input.type_.print(cache))?;
+                    write!(f, "{}", input.type_.print(cache, depth))?;
                 }
                 if i + 1 < self.values.len() {
                     write!(f, ", ")?;
@@ -943,21 +975,29 @@ impl clean::Arguments {
 }
 
 impl clean::FnRetTy {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| match self {
             clean::Return(clean::Tuple(tys)) if tys.is_empty() => Ok(()),
-            clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print(cache)),
-            clean::Return(ty) => write!(f, " -&gt; {}", ty.print(cache)),
+            clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print(cache, depth)),
+            clean::Return(ty) => write!(f, " -&gt; {}", ty.print(cache, depth)),
             clean::DefaultReturn => Ok(()),
         })
     }
 }
 
 impl clean::BareFunctionDecl {
-    fn print_hrtb_with_space<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    fn print_hrtb_with_space<'a>(
+        &'a self,
+        cache: &'a Cache,
+        depth: usize,
+    ) -> impl fmt::Display + 'a {
         display_fn(move |f| {
             if !self.generic_params.is_empty() {
-                write!(f, "for<{}> ", comma_sep(self.generic_params.iter().map(|g| g.print(cache))))
+                write!(
+                    f,
+                    "for<{}> ",
+                    comma_sep(self.generic_params.iter().map(|g| g.print(cache, depth)))
+                )
             } else {
                 Ok(())
             }
@@ -966,24 +1006,24 @@ impl clean::BareFunctionDecl {
 }
 
 impl clean::FnDecl {
-    crate fn print<'a>(&'a self, cache: &'a Cache) -> impl fmt::Display + 'a {
+    crate fn print<'a>(&'a self, cache: &'a Cache, depth: usize) -> impl fmt::Display + 'a {
         display_fn(move |f| {
             let ellipsis = if self.c_variadic { ", ..." } else { "" };
             if f.alternate() {
                 write!(
                     f,
                     "({args:#}{ellipsis}){arrow:#}",
-                    args = self.inputs.print(cache),
+                    args = self.inputs.print(cache, depth),
                     ellipsis = ellipsis,
-                    arrow = self.output.print(cache)
+                    arrow = self.output.print(cache, depth)
                 )
             } else {
                 write!(
                     f,
                     "({args}{ellipsis}){arrow}",
-                    args = self.inputs.print(cache),
+                    args = self.inputs.print(cache, depth),
                     ellipsis = ellipsis,
-                    arrow = self.output.print(cache)
+                    arrow = self.output.print(cache, depth)
                 )
             }
         })
@@ -991,7 +1031,7 @@ impl clean::FnDecl {
 }
 
 impl Function<'_> {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache, depth: usize) -> impl fmt::Display + 'b {
         display_fn(move |f| {
             let &Function { decl, header_len, indent, asyncness } = self;
             let amp = if f.alternate() { "&" } else { "&amp;" };
@@ -1027,11 +1067,11 @@ impl Function<'_> {
                         }
                         clean::SelfExplicit(ref typ) => {
                             if f.alternate() {
-                                args.push_str(&format!("self: {:#}", typ.print(cache)));
+                                args.push_str(&format!("self: {:#}", typ.print(cache, depth)));
                             } else {
-                                args.push_str(&format!("self: {}", typ.print(cache)));
+                                args.push_str(&format!("self: {}", typ.print(cache, depth)));
                             }
-                            args_plain.push_str(&format!("self: {:#}", typ.print(cache)));
+                            args_plain.push_str(&format!("self: {:#}", typ.print(cache, depth)));
                         }
                     }
                 } else {
@@ -1045,11 +1085,11 @@ impl Function<'_> {
                     }
 
                     if f.alternate() {
-                        args.push_str(&format!("{:#}", input.type_.print(cache)));
+                        args.push_str(&format!("{:#}", input.type_.print(cache, depth)));
                     } else {
-                        args.push_str(&input.type_.print(cache).to_string());
+                        args.push_str(&input.type_.print(cache, depth).to_string());
                     }
-                    args_plain.push_str(&format!("{:#}", input.type_.print(cache)));
+                    args_plain.push_str(&format!("{:#}", input.type_.print(cache, depth)));
                 }
                 if i + 1 < decl.inputs.values.len() {
                     args.push(',');
@@ -1070,11 +1110,11 @@ impl Function<'_> {
                 Cow::Borrowed(&decl.output)
             };
 
-            let arrow_plain = format!("{:#}", &output.print(cache));
+            let arrow_plain = format!("{:#}", &output.print(cache, depth));
             let arrow = if f.alternate() {
-                format!("{:#}", &output.print(cache))
+                format!("{:#}", &output.print(cache, depth))
             } else {
-                output.print(cache).to_string()
+                output.print(cache, depth).to_string()
             };
 
             let declaration_len = header_len + args_plain.len() + arrow_plain.len();
@@ -1106,6 +1146,7 @@ impl clean::Visibility {
         tcx: TyCtxt<'tcx>,
         item_did: DefId,
         cache: &Cache,
+        depth: usize,
     ) -> impl fmt::Display + 'tcx {
         use rustc_span::symbol::kw;
 
@@ -1137,7 +1178,7 @@ impl clean::Visibility {
                         path.data[0].data.get_opt_name().expect("modules are always named");
                     // modified from `resolved_path()` to work with `DefPathData`
                     let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
-                    let anchor = anchor(vis_did, &last_name.as_str(), cache).to_string();
+                    let anchor = anchor(vis_did, &last_name.as_str(), cache, depth).to_string();
 
                     let mut s = "pub(".to_owned();
                     if path.data.len() != 1
@@ -1198,20 +1239,20 @@ impl PrintWithSpace for hir::Mutability {
 }
 
 impl clean::Import {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache, depth: usize) -> impl fmt::Display + 'b {
         display_fn(move |f| match self.kind {
             clean::ImportKind::Simple(name) => {
                 if name == self.source.path.last() {
-                    write!(f, "use {};", self.source.print(cache))
+                    write!(f, "use {};", self.source.print(cache, depth))
                 } else {
-                    write!(f, "use {} as {};", self.source.print(cache), name)
+                    write!(f, "use {} as {};", self.source.print(cache, depth), name)
                 }
             }
             clean::ImportKind::Glob => {
                 if self.source.path.segments.is_empty() {
                     write!(f, "use *;")
                 } else {
-                    write!(f, "use {}::*;", self.source.print(cache))
+                    write!(f, "use {}::*;", self.source.print(cache, depth))
                 }
             }
         })
@@ -1219,16 +1260,16 @@ impl clean::Import {
 }
 
 impl clean::ImportSource {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache, depth: usize) -> impl fmt::Display + 'b {
         display_fn(move |f| match self.did {
-            Some(did) => resolved_path(f, did, &self.path, true, false, cache),
+            Some(did) => resolved_path(f, did, &self.path, true, false, cache, depth),
             _ => {
                 for seg in &self.path.segments[..self.path.segments.len() - 1] {
                     write!(f, "{}::", seg.name)?;
                 }
                 let name = self.path.last_name();
                 if let hir::def::Res::PrimTy(p) = self.path.res {
-                    primitive_link(f, PrimitiveType::from(p), &*name, cache)?;
+                    primitive_link(f, PrimitiveType::from(p), &*name, cache, depth)?;
                 } else {
                     write!(f, "{}", name)?;
                 }
@@ -1239,23 +1280,23 @@ impl clean::ImportSource {
 }
 
 impl clean::TypeBinding {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache, depth: usize) -> impl fmt::Display + 'b {
         display_fn(move |f| {
             f.write_str(&*self.name.as_str())?;
             match self.kind {
                 clean::TypeBindingKind::Equality { ref ty } => {
                     if f.alternate() {
-                        write!(f, " = {:#}", ty.print(cache))?;
+                        write!(f, " = {:#}", ty.print(cache, depth))?;
                     } else {
-                        write!(f, " = {}", ty.print(cache))?;
+                        write!(f, " = {}", ty.print(cache, depth))?;
                     }
                 }
                 clean::TypeBindingKind::Constraint { ref bounds } => {
                     if !bounds.is_empty() {
                         if f.alternate() {
-                            write!(f, ": {:#}", print_generic_bounds(bounds, cache))?;
+                            write!(f, ": {:#}", print_generic_bounds(bounds, cache, depth))?;
                         } else {
-                            write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache))?;
+                            write!(f, ":&nbsp;{}", print_generic_bounds(bounds, cache, depth))?;
                         }
                     }
                 }
@@ -1280,10 +1321,10 @@ crate fn print_default_space<'a>(v: bool) -> &'a str {
 }
 
 impl clean::GenericArg {
-    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache) -> impl fmt::Display + 'b {
+    crate fn print<'b, 'a: 'b>(&'a self, cache: &'b Cache, depth: usize) -> impl fmt::Display + 'b {
         display_fn(move |f| match self {
             clean::GenericArg::Lifetime(lt) => fmt::Display::fmt(&lt.print(), f),
-            clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cache), f),
+            clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(cache, depth), f),
             clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(), f),
         })
     }
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 976168a9ac407..475e633f77ab0 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -19,7 +19,7 @@ use super::print_item::{full_path, item_path, print_item};
 use super::write_shared::write_shared;
 use super::{
     print_sidebar, settings, AllTypes, NameDoc, SharedContext, StylePath, BASIC_KEYWORDS,
-    CURRENT_DEPTH, INITIAL_IDS,
+    INITIAL_IDS,
 };
 
 use crate::clean::{self, AttributesExt};
@@ -71,6 +71,10 @@ crate struct Context<'tcx> {
 }
 
 impl<'tcx> Context<'tcx> {
+    pub(super) fn depth(&self) -> usize {
+        self.current.len()
+    }
+
     pub(super) fn path(&self, filename: &str) -> PathBuf {
         // We use splitn vs Path::extension here because we might get a filename
         // like `style.min.css` and we want to process that into
@@ -102,12 +106,6 @@ impl<'tcx> Context<'tcx> {
     }
 
     fn render_item(&self, it: &clean::Item, pushname: bool) -> String {
-        // A little unfortunate that this is done like this, but it sure
-        // does make formatting *a lot* nicer.
-        CURRENT_DEPTH.with(|slot| {
-            slot.set(self.current.len());
-        });
-
         let mut title = if it.is_primitive() || it.is_keyword() {
             // No need to include the namespace for primitive types and keywords
             String::new()
@@ -418,8 +416,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             redirections: if generate_redirect_map { Some(Default::default()) } else { None },
         };
 
-        CURRENT_DEPTH.with(|s| s.set(0));
-
         // Write shared runs within a flock; disable thread dispatching of IO temporarily.
         Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
         write_shared(&cx, &krate, index, &md_opts)?;
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 50cae50c2c3eb..e8257ad362151 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -34,7 +34,7 @@ mod write_shared;
 
 crate use context::*;
 
-use std::cell::{Cell, RefCell};
+use std::cell::RefCell;
 use std::collections::VecDeque;
 use std::default::Default;
 use std::fmt;
@@ -291,8 +291,6 @@ crate struct StylePath {
     crate disabled: bool,
 }
 
-thread_local!(crate static CURRENT_DEPTH: Cell<usize> = Cell::new(0));
-
 crate const INITIAL_IDS: [&'static str; 15] = [
     "main",
     "search",
@@ -670,11 +668,14 @@ fn document_short(
         return;
     }
     if let Some(s) = item.doc_value() {
-        let mut summary_html = MarkdownSummaryLine(&s, &item.links(&cx.cache)).into_string();
+        let mut summary_html =
+            MarkdownSummaryLine(&s, &item.links(&cx.cache, cx.depth())).into_string();
 
         if s.contains('\n') {
-            let link =
-                format!(r#" <a href="{}">Read more</a>"#, naive_assoc_href(item, link, cx.cache()));
+            let link = format!(
+                r#" <a href="{}">Read more</a>"#,
+                naive_assoc_href(item, link, cx.cache(), cx.depth())
+            );
 
             if let Some(idx) = summary_html.rfind("</p>") {
                 summary_html.insert_str(idx, &link);
@@ -709,7 +710,7 @@ fn document_full(
 ) {
     if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) {
         debug!("Doc block: =====\n{}\n=====", s);
-        render_markdown(w, cx, &*s, item.links(&cx.cache), prefix, is_hidden);
+        render_markdown(w, cx, &*s, item.links(&cx.cache, cx.depth()), prefix, is_hidden);
     } else if !prefix.is_empty() {
         if is_hidden {
             w.write_str("<div class=\"docblock hidden\">");
@@ -893,7 +894,12 @@ fn render_impls(
     w.write_str(&impls.join(""));
 }
 
-fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>, cache: &Cache) -> String {
+fn naive_assoc_href(
+    it: &clean::Item,
+    link: AssocItemLink<'_>,
+    cache: &Cache,
+    depth: usize,
+) -> String {
     use crate::formats::item_type::ItemType::*;
 
     let name = it.name.as_ref().unwrap();
@@ -907,7 +913,7 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>, cache: &Cache) ->
         AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
         AssocItemLink::Anchor(None) => anchor,
         AssocItemLink::GotoSource(did, _) => {
-            href(did, cache).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
+            href(did, cache, depth).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
         }
     }
 }
@@ -925,10 +931,10 @@ fn assoc_const(
         w,
         "{}{}const <a href=\"{}\" class=\"constant\"><b>{}</b></a>: {}",
         extra,
-        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
-        naive_assoc_href(it, link, cx.cache()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
+        naive_assoc_href(it, link, cx.cache(), cx.depth()),
         it.name.as_ref().unwrap(),
-        ty.print(cx.cache())
+        ty.print(cx.cache(), cx.depth())
     );
 }
 
@@ -940,19 +946,20 @@ fn assoc_type(
     link: AssocItemLink<'_>,
     extra: &str,
     cache: &Cache,
+    depth: usize,
 ) {
     write!(
         w,
         "{}type <a href=\"{}\" class=\"type\">{}</a>",
         extra,
-        naive_assoc_href(it, link, cache),
+        naive_assoc_href(it, link, cache, depth),
         it.name.as_ref().unwrap()
     );
     if !bounds.is_empty() {
-        write!(w, ": {}", print_generic_bounds(bounds, cache))
+        write!(w, ": {}", print_generic_bounds(bounds, cache, depth))
     }
     if let Some(default) = default {
-        write!(w, " = {}", default.print(cache))
+        write!(w, " = {}", default.print(cache, depth))
     }
 }
 
@@ -1016,19 +1023,21 @@ fn render_assoc_item(
                     ItemType::TyMethod
                 };
 
-                href(did, cx.cache()).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor)
+                href(did, cx.cache(), cx.depth())
+                    .map(|p| format!("{}#{}.{}", p.0, ty, name))
+                    .unwrap_or(anchor)
             }
         };
         let mut header_len = format!(
             "{}{}{}{}{}{:#}fn {}{:#}",
-            meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache()),
+            meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache(), cx.depth()),
             header.constness.print_with_space(),
             header.asyncness.print_with_space(),
             header.unsafety.print_with_space(),
             print_default_space(meth.is_default()),
             print_abi_with_space(header.abi),
             name,
-            g.print(cx.cache())
+            g.print(cx.cache(), cx.depth())
         )
         .len();
         let (indent, end_newline) = if parent == ItemType::Trait {
@@ -1043,7 +1052,7 @@ fn render_assoc_item(
             "{}{}{}{}{}{}{}fn <a href=\"{href}\" class=\"fnname\">{name}</a>\
              {generics}{decl}{spotlight}{where_clause}",
             if parent == ItemType::Trait { "    " } else { "" },
-            meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache()),
+            meth.visibility.print_with_space(cx.tcx(), meth.def_id, cx.cache(), cx.depth()),
             header.constness.print_with_space(),
             header.asyncness.print_with_space(),
             header.unsafety.print_with_space(),
@@ -1051,11 +1060,12 @@ fn render_assoc_item(
             print_abi_with_space(header.abi),
             href = href,
             name = name,
-            generics = g.print(cx.cache()),
+            generics = g.print(cx.cache(), cx.depth()),
             decl = Function { decl: d, header_len, indent, asyncness: header.asyncness }
-                .print(cx.cache()),
-            spotlight = spotlight_decl(&d, cx.cache()),
-            where_clause = WhereClause { gens: g, indent, end_newline }.print(cx.cache())
+                .print(cx.cache(), cx.depth()),
+            spotlight = spotlight_decl(&d, cx.cache(), cx.depth()),
+            where_clause =
+                WhereClause { gens: g, indent, end_newline }.print(cx.cache(), cx.depth())
         )
     }
     match *item.kind {
@@ -1083,6 +1093,7 @@ fn render_assoc_item(
             link,
             if parent == ItemType::Trait { "    " } else { "" },
             cx.cache(),
+            cx.depth(),
         ),
         _ => panic!("render_assoc_item called on non-associated-item"),
     }
@@ -1171,9 +1182,9 @@ fn render_assoc_items(
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
                 let id = cx.derive_id(small_url_encode(format!(
                     "deref-methods-{:#}",
-                    type_.print(cx.cache())
+                    type_.print(cx.cache(), cx.depth())
                 )));
-                debug!("Adding {} to deref id map", type_.print(cx.cache()));
+                debug!("Adding {} to deref id map", type_.print(cx.cache(), cx.depth()));
                 cx.deref_id_map
                     .borrow_mut()
                     .insert(type_.def_id_full(cx.cache()).unwrap(), id.clone());
@@ -1184,8 +1195,8 @@ fn render_assoc_items(
                          <a href=\"#{id}\" class=\"anchor\"></a>\
                      </h2>",
                     id = id,
-                    trait_ = trait_.print(cx.cache()),
-                    type_ = type_.print(cx.cache()),
+                    trait_ = trait_.print(cx.cache(), cx.depth()),
+                    type_ = type_.print(cx.cache(), cx.depth()),
                 );
                 RenderMode::ForDeref { mut_: deref_mut_ }
             }
@@ -1337,7 +1348,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, cache: &Cache) -> bo
     }
 }
 
-fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
+fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache, depth: usize) -> String {
     let mut out = Buffer::html();
     let mut trait_ = String::new();
 
@@ -1353,16 +1364,16 @@ fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
                             &mut out,
                             "<h3 class=\"notable\">Notable traits for {}</h3>\
                              <code class=\"content\">",
-                            impl_.for_.print(cache)
+                            impl_.for_.print(cache, depth)
                         );
-                        trait_.push_str(&impl_.for_.print(cache).to_string());
+                        trait_.push_str(&impl_.for_.print(cache, depth).to_string());
                     }
 
                     //use the "where" class here to make it small
                     write!(
                         &mut out,
                         "<span class=\"where fmt-newline\">{}</span>",
-                        impl_.print(cache, false)
+                        impl_.print(cache, false, depth)
                     );
                     let t_did = impl_.trait_.def_id_full(cache).unwrap();
                     for it in &impl_.items {
@@ -1376,6 +1387,7 @@ fn spotlight_decl(decl: &clean::FnDecl, cache: &Cache) -> String {
                                 AssocItemLink::GotoSource(t_did, &FxHashSet::default()),
                                 "",
                                 cache,
+                                depth,
                             );
                             out.push_str(";</span>");
                         }
@@ -1421,9 +1433,12 @@ fn render_impl(
         let id = cx.derive_id(match i.inner_impl().trait_ {
             Some(ref t) => {
                 if is_on_foreign_type {
-                    get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx.cache())
+                    get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx.cache(), cx.depth())
                 } else {
-                    format!("impl-{}", small_url_encode(format!("{:#}", t.print(cx.cache()))))
+                    format!(
+                        "impl-{}",
+                        small_url_encode(format!("{:#}", t.print(cx.cache(), cx.depth())))
+                    )
                 }
             }
             None => "impl".to_string(),
@@ -1435,7 +1450,7 @@ fn render_impl(
         };
         if let Some(use_absolute) = use_absolute {
             write!(w, "<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">", id, aliases);
-            write!(w, "{}", i.inner_impl().print(cx.cache(), use_absolute));
+            write!(w, "{}", i.inner_impl().print(cx.cache(), use_absolute, cx.depth()));
             if show_def_docs {
                 for it in &i.inner_impl().items {
                     if let clean::TypedefItem(ref tydef, _) = *it.kind {
@@ -1448,6 +1463,7 @@ fn render_impl(
                             AssocItemLink::Anchor(None),
                             "",
                             cx.cache(),
+                            cx.depth(),
                         );
                         w.write_str(";</span>");
                     }
@@ -1460,7 +1476,7 @@ fn render_impl(
                 "<h3 id=\"{}\" class=\"impl\"{}><code class=\"in-band\">{}</code>",
                 id,
                 aliases,
-                i.inner_impl().print(cx.cache(), false)
+                i.inner_impl().print(cx.cache(), false, cx.depth())
             );
         }
         write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
@@ -1487,7 +1503,7 @@ fn render_impl(
                 "<div class=\"docblock\">{}</div>",
                 Markdown(
                     &*dox,
-                    &i.impl_item.links(&cx.cache),
+                    &i.impl_item.links(&cx.cache, cx.depth()),
                     &mut ids,
                     cx.shared.codes,
                     cx.shared.edition,
@@ -1560,6 +1576,7 @@ fn render_impl(
                     link.anchor(&id),
                     "",
                     cx.cache(),
+                    cx.depth(),
                 );
                 w.write_str("</code></h4>");
             }
@@ -1581,7 +1598,16 @@ fn render_impl(
             clean::AssocTypeItem(ref bounds, ref default) => {
                 let id = cx.derive_id(format!("{}.{}", item_type, name));
                 write!(w, "<h4 id=\"{}\" class=\"{}{}\"><code>", id, item_type, extra_class);
-                assoc_type(w, item, bounds, default.as_ref(), link.anchor(&id), "", cx.cache());
+                assoc_type(
+                    w,
+                    item,
+                    bounds,
+                    default.as_ref(),
+                    link.anchor(&id),
+                    "",
+                    cx.cache(),
+                    cx.depth(),
+                );
                 w.write_str("</code></h4>");
             }
             clean::StrippedItem(..) => return,
@@ -1924,9 +1950,10 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
                     .iter()
                     .filter_map(|it| {
                         if let Some(ref i) = it.inner_impl().trait_ {
-                            let i_display = format!("{:#}", i.print(cx.cache()));
+                            let i_display = format!("{:#}", i.print(cx.cache(), cx.depth()));
                             let out = Escape(&i_display);
-                            let encoded = small_url_encode(format!("{:#}", i.print(cx.cache())));
+                            let encoded =
+                                small_url_encode(format!("{:#}", i.print(cx.cache(), cx.depth())));
                             let generated = format!(
                                 "<a href=\"#impl-{}\">{}{}</a>",
                                 encoded,
@@ -2038,8 +2065,11 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
                     out,
                     "<a class=\"sidebar-title\" href=\"#{}\">Methods from {}&lt;Target={}&gt;</a>",
                     id,
-                    Escape(&format!("{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print(c))),
-                    Escape(&format!("{:#}", real_target.print(c))),
+                    Escape(&format!(
+                        "{:#}",
+                        impl_.inner_impl().trait_.as_ref().unwrap().print(c, cx.depth())
+                    )),
+                    Escape(&format!("{:#}", real_target.print(c, cx.depth()))),
                 );
                 // We want links' order to be reproducible so we don't use unstable sort.
                 ret.sort();
@@ -2096,17 +2126,26 @@ fn get_id_for_impl_on_foreign_type(
     for_: &clean::Type,
     trait_: &clean::Type,
     cache: &Cache,
+    depth: usize,
 ) -> String {
-    small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cache), for_.print(cache)))
+    small_url_encode(format!(
+        "impl-{:#}-for-{:#}",
+        trait_.print(cache, depth),
+        for_.print(cache, depth)
+    ))
 }
 
-fn extract_for_impl_name(item: &clean::Item, cache: &Cache) -> Option<(String, String)> {
+fn extract_for_impl_name(
+    item: &clean::Item,
+    cache: &Cache,
+    depth: usize,
+) -> Option<(String, String)> {
     match *item.kind {
         clean::ItemKind::ImplItem(ref i) => {
             if let Some(ref trait_) = i.trait_ {
                 Some((
-                    format!("{:#}", i.for_.print(cache)),
-                    get_id_for_impl_on_foreign_type(&i.for_, trait_, cache),
+                    format!("{:#}", i.for_.print(cache, depth)),
+                    get_id_for_impl_on_foreign_type(&i.for_, trait_, cache, depth),
                 ))
             } else {
                 None
@@ -2194,7 +2233,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
                     .def_id_full(cx.cache())
                     .map_or(false, |d| !cx.cache.paths.contains_key(&d))
             })
-            .filter_map(|i| extract_for_impl_name(&i.impl_item, cx.cache()))
+            .filter_map(|i| extract_for_impl_name(&i.impl_item, cx.cache(), cx.depth()))
             .collect::<Vec<_>>();
 
         if !res.is_empty() {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 6cdd3838023e6..d574bb04bc879 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -247,15 +247,30 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                     Some(ref src) => write!(
                         w,
                         "<tr><td><code>{}extern crate {} as {};",
-                        myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()),
-                        anchor(myitem.def_id, &*src.as_str(), cx.cache()),
+                        myitem.visibility.print_with_space(
+                            cx.tcx(),
+                            myitem.def_id,
+                            cx.cache(),
+                            cx.depth(),
+                        ),
+                        anchor(myitem.def_id, &*src.as_str(), cx.cache(), cx.depth()),
                         myitem.name.as_ref().unwrap(),
                     ),
                     None => write!(
                         w,
                         "<tr><td><code>{}extern crate {};",
-                        myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()),
-                        anchor(myitem.def_id, &*myitem.name.as_ref().unwrap().as_str(), cx.cache()),
+                        myitem.visibility.print_with_space(
+                            cx.tcx(),
+                            myitem.def_id,
+                            cx.cache(),
+                            cx.depth(),
+                        ),
+                        anchor(
+                            myitem.def_id,
+                            &*myitem.name.as_ref().unwrap().as_str(),
+                            cx.cache(),
+                            cx.depth(),
+                        ),
                     ),
                 }
                 w.write_str("</code></td></tr>");
@@ -265,8 +280,13 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                 write!(
                     w,
                     "<tr><td><code>{}{}</code></td></tr>",
-                    myitem.visibility.print_with_space(cx.tcx(), myitem.def_id, cx.cache()),
-                    import.print(cx.cache())
+                    myitem.visibility.print_with_space(
+                        cx.tcx(),
+                        myitem.def_id,
+                        cx.cache(),
+                        cx.depth()
+                    ),
+                    import.print(cx.cache(), cx.depth())
                 );
             }
 
@@ -297,7 +317,8 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
                      </tr>",
                     name = *myitem.name.as_ref().unwrap(),
                     stab_tags = extra_info_tags(myitem, item, cx.tcx()),
-                    docs = MarkdownSummaryLine(&doc_value, &myitem.links(&cx.cache)).into_string(),
+                    docs = MarkdownSummaryLine(&doc_value, &myitem.links(&cx.cache, cx.depth()))
+                        .into_string(),
                     class = myitem.type_(),
                     add = add,
                     stab = stab.unwrap_or_else(String::new),
@@ -366,13 +387,13 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
 fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
     let header_len = format!(
         "{}{}{}{}{:#}fn {}{:#}",
-        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
         f.header.constness.print_with_space(),
         f.header.asyncness.print_with_space(),
         f.header.unsafety.print_with_space(),
         print_abi_with_space(f.header.abi),
         it.name.as_ref().unwrap(),
-        f.generics.print(cx.cache())
+        f.generics.print(cx.cache(), cx.depth())
     )
     .len();
     w.write_str("<pre class=\"rust fn\">");
@@ -381,24 +402,24 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
         w,
         "{vis}{constness}{asyncness}{unsafety}{abi}fn \
          {name}{generics}{decl}{spotlight}{where_clause}</pre>",
-        vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
+        vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
         constness = f.header.constness.print_with_space(),
         asyncness = f.header.asyncness.print_with_space(),
         unsafety = f.header.unsafety.print_with_space(),
         abi = print_abi_with_space(f.header.abi),
         name = it.name.as_ref().unwrap(),
-        generics = f.generics.print(cx.cache()),
-        where_clause =
-            WhereClause { gens: &f.generics, indent: 0, end_newline: true }.print(cx.cache()),
+        generics = f.generics.print(cx.cache(), cx.depth()),
+        where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true }
+            .print(cx.cache(), cx.depth()),
         decl = Function { decl: &f.decl, header_len, indent: 0, asyncness: f.header.asyncness }
-            .print(cx.cache()),
-        spotlight = spotlight_decl(&f.decl, cx.cache()),
+            .print(cx.cache(), cx.depth()),
+        spotlight = spotlight_decl(&f.decl, cx.cache(), cx.depth()),
     );
     document(w, cx, it, None)
 }
 
 fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
-    let bounds = bounds(&t.bounds, false, cx.cache());
+    let bounds = bounds(&t.bounds, false, cx.cache(), cx.depth());
     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<_>>();
     let required = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>();
@@ -411,17 +432,17 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
         write!(
             w,
             "{}{}{}trait {}{}{}",
-            it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
+            it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
             t.unsafety.print_with_space(),
             if t.is_auto { "auto " } else { "" },
             it.name.as_ref().unwrap(),
-            t.generics.print(cx.cache()),
+            t.generics.print(cx.cache(), cx.depth()),
             bounds
         );
 
         if !t.generics.where_predicates.is_empty() {
             let where_ = WhereClause { gens: &t.generics, indent: 0, end_newline: true };
-            write!(w, "{}", where_.print(cx.cache()));
+            write!(w, "{}", where_.print(cx.cache(), cx.depth()));
         } else {
             w.write_str(" ");
         }
@@ -594,8 +615,8 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
         let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
             local.iter().partition(|i| i.inner_impl().synthetic);
 
-        synthetic.sort_by(|a, b| compare_impl(a, b, cx.cache()));
-        concrete.sort_by(|a, b| compare_impl(a, b, cx.cache()));
+        synthetic.sort_by(|a, b| compare_impl(a, b, cx.cache(), cx.depth()));
+        concrete.sort_by(|a, b| compare_impl(a, b, cx.cache(), cx.depth()));
 
         if !foreign.is_empty() {
             write_small_section_header(w, "foreign-impls", "Implementations on Foreign Types", "");
@@ -700,9 +721,10 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
         w,
         "trait {}{}{} = {};</pre>",
         it.name.as_ref().unwrap(),
-        t.generics.print(cx.cache()),
-        WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()),
-        bounds(&t.bounds, true, cx.cache())
+        t.generics.print(cx.cache(), cx.depth()),
+        WhereClause { gens: &t.generics, indent: 0, end_newline: true }
+            .print(cx.cache(), cx.depth()),
+        bounds(&t.bounds, true, cx.cache(), cx.depth())
     );
 
     document(w, cx, it, None);
@@ -721,10 +743,10 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
         w,
         "type {}{}{where_clause} = impl {bounds};</pre>",
         it.name.as_ref().unwrap(),
-        t.generics.print(cx.cache()),
-        where_clause =
-            WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()),
-        bounds = bounds(&t.bounds, false, cx.cache())
+        t.generics.print(cx.cache(), cx.depth()),
+        where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true }
+            .print(cx.cache(), cx.depth()),
+        bounds = bounds(&t.bounds, false, cx.cache(), cx.depth())
     );
 
     document(w, cx, it, None);
@@ -743,10 +765,10 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
         w,
         "type {}{}{where_clause} = {type_};</pre>",
         it.name.as_ref().unwrap(),
-        t.generics.print(cx.cache()),
-        where_clause =
-            WhereClause { gens: &t.generics, indent: 0, end_newline: true }.print(cx.cache()),
-        type_ = t.type_.print(cx.cache())
+        t.generics.print(cx.cache(), cx.depth()),
+        where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true }
+            .print(cx.cache(), cx.depth()),
+        type_ = t.type_.print(cx.cache(), cx.depth())
     );
 
     document(w, cx, it, None);
@@ -793,7 +815,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
                 id = id,
                 name = name,
                 shortty = ItemType::StructField,
-                ty = ty.print(cx.cache())
+                ty = ty.print(cx.cache(), cx.depth())
             );
             if let Some(stability_class) = field.stability_class(cx.tcx()) {
                 write!(w, "<span class=\"stab {stab}\"></span>", stab = stability_class);
@@ -811,10 +833,11 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
         write!(
             w,
             "{}enum {}{}{}",
-            it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
+            it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
             it.name.as_ref().unwrap(),
-            e.generics.print(cx.cache()),
-            WhereClause { gens: &e.generics, indent: 0, end_newline: true }.print(cx.cache())
+            e.generics.print(cx.cache(), cx.depth()),
+            WhereClause { gens: &e.generics, indent: 0, end_newline: true }
+                .print(cx.cache(), cx.depth())
         );
         if e.variants.is_empty() && !e.variants_stripped {
             w.write_str(" {}");
@@ -832,7 +855,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                                 if i > 0 {
                                     w.write_str(",&nbsp;")
                                 }
-                                write!(w, "{}", ty.print(cx.cache()));
+                                write!(w, "{}", ty.print(cx.cache(), cx.depth()));
                             }
                             w.write_str(")");
                         }
@@ -879,7 +902,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                     if i > 0 {
                         w.write_str(",&nbsp;");
                     }
-                    write!(w, "{}", ty.print(cx.cache()));
+                    write!(w, "{}", ty.print(cx.cache(), cx.depth()));
                 }
                 w.write_str(")");
             }
@@ -916,7 +939,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
                              </span>",
                             id = id,
                             f = field.name.as_ref().unwrap(),
-                            t = ty.print(cx.cache())
+                            t = ty.print(cx.cache(), cx.depth())
                         );
                         document(w, cx, field, Some(variant));
                     }
@@ -985,9 +1008,9 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
     write!(
         w,
         "{vis}const {name}: {typ}",
-        vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
+        vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
         name = it.name.as_ref().unwrap(),
-        typ = c.type_.print(cx.cache()),
+        typ = c.type_.print(cx.cache(), cx.depth()),
     );
 
     if c.value.is_some() || c.is_literal {
@@ -1054,7 +1077,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
                     item_type = ItemType::StructField,
                     id = id,
                     name = field.name.as_ref().unwrap(),
-                    ty = ty.print(cx.cache())
+                    ty = ty.print(cx.cache(), cx.depth())
                 );
                 document(w, cx, field, Some(it));
             }
@@ -1069,10 +1092,10 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
     write!(
         w,
         "{vis}static {mutability}{name}: {typ}</pre>",
-        vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
+        vis = it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
         mutability = s.mutability.print_with_space(),
         name = it.name.as_ref().unwrap(),
-        typ = s.type_.print(cx.cache())
+        typ = s.type_.print(cx.cache(), cx.depth())
     );
     document(w, cx, it, None)
 }
@@ -1083,7 +1106,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
     write!(
         w,
         "    {}type {};\n}}</pre>",
-        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
         it.name.as_ref().unwrap(),
     );
 
@@ -1147,7 +1170,12 @@ pub(super) fn item_path(ty: ItemType, name: &str) -> String {
     }
 }
 
-fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cache: &Cache) -> String {
+fn bounds(
+    t_bounds: &[clean::GenericBound],
+    trait_alias: bool,
+    cache: &Cache,
+    depth: usize,
+) -> String {
     let mut bounds = String::new();
     if !t_bounds.is_empty() {
         if !trait_alias {
@@ -1157,7 +1185,7 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cache: &Cache) ->
             if i > 0 {
                 bounds.push_str(" + ");
             }
-            bounds.push_str(&p.print(cache).to_string());
+            bounds.push_str(&p.print(cache, depth).to_string());
         }
     }
     bounds
@@ -1187,9 +1215,9 @@ fn render_stability_since(
     )
 }
 
-fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cache: &Cache) -> Ordering {
-    let lhs = format!("{}", lhs.inner_impl().print(cache, false));
-    let rhs = format!("{}", rhs.inner_impl().print(cache, false));
+fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cache: &Cache, depth: usize) -> Ordering {
+    let lhs = format!("{}", lhs.inner_impl().print(cache, false, depth));
+    let rhs = format!("{}", rhs.inner_impl().print(cache, false, depth));
 
     // lhs and rhs are formatted as HTML, which may be unnecessary
     compare_names(&lhs, &rhs)
@@ -1242,13 +1270,17 @@ fn render_union(
     write!(
         w,
         "{}{}{}",
-        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
         if structhead { "union " } else { "" },
         it.name.as_ref().unwrap()
     );
     if let Some(g) = g {
-        write!(w, "{}", g.print(cx.cache()));
-        write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true }.print(cx.cache()));
+        write!(w, "{}", g.print(cx.cache(), cx.depth()));
+        write!(
+            w,
+            "{}",
+            WhereClause { gens: g, indent: 0, end_newline: true }.print(cx.cache(), cx.depth())
+        );
     }
 
     write!(w, " {{\n{}", tab);
@@ -1257,9 +1289,9 @@ fn render_union(
             write!(
                 w,
                 "    {}{}: {},\n{}",
-                field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
+                field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache(), cx.depth()),
                 field.name.as_ref().unwrap(),
-                ty.print(cx.cache()),
+                ty.print(cx.cache(), cx.depth()),
                 tab
             );
         }
@@ -1284,12 +1316,12 @@ fn render_struct(
     write!(
         w,
         "{}{}{}",
-        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache()),
+        it.visibility.print_with_space(cx.tcx(), it.def_id, cx.cache(), cx.depth()),
         if structhead { "struct " } else { "" },
         it.name.as_ref().unwrap()
     );
     if let Some(g) = g {
-        write!(w, "{}", g.print(cx.cache()))
+        write!(w, "{}", g.print(cx.cache(), cx.depth()))
     }
     match ty {
         CtorKind::Fictive => {
@@ -1297,7 +1329,8 @@ fn render_struct(
                 write!(
                     w,
                     "{}",
-                    WhereClause { gens: g, indent: 0, end_newline: true }.print(cx.cache())
+                    WhereClause { gens: g, indent: 0, end_newline: true }
+                        .print(cx.cache(), cx.depth())
                 )
             }
             let mut has_visible_fields = false;
@@ -1308,9 +1341,14 @@ fn render_struct(
                         w,
                         "\n{}    {}{}: {},",
                         tab,
-                        field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
+                        field.visibility.print_with_space(
+                            cx.tcx(),
+                            field.def_id,
+                            cx.cache(),
+                            cx.depth()
+                        ),
                         field.name.as_ref().unwrap(),
-                        ty.print(cx.cache())
+                        ty.print(cx.cache(), cx.depth())
                     );
                     has_visible_fields = true;
                 }
@@ -1340,8 +1378,13 @@ fn render_struct(
                         write!(
                             w,
                             "{}{}",
-                            field.visibility.print_with_space(cx.tcx(), field.def_id, cx.cache()),
-                            ty.print(cx.cache())
+                            field.visibility.print_with_space(
+                                cx.tcx(),
+                                field.def_id,
+                                cx.cache(),
+                                cx.depth()
+                            ),
+                            ty.print(cx.cache(), cx.depth())
                         )
                     }
                     _ => unreachable!(),
@@ -1352,7 +1395,8 @@ fn render_struct(
                 write!(
                     w,
                     "{}",
-                    WhereClause { gens: g, indent: 0, end_newline: false }.print(cx.cache())
+                    WhereClause { gens: g, indent: 0, end_newline: false }
+                        .print(cx.cache(), cx.depth())
                 )
             }
             w.write_str(";");
@@ -1363,7 +1407,8 @@ fn render_struct(
                 write!(
                     w,
                     "{}",
-                    WhereClause { gens: g, indent: 0, end_newline: false }.print(cx.cache())
+                    WhereClause { gens: g, indent: 0, end_newline: false }
+                        .print(cx.cache(), cx.depth())
                 )
             }
             w.write_str(";");
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index cbf0f9a4927c6..d4b889c3a399b 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -471,7 +471,7 @@ themePicker.onblur = handleThemeButtonsBlur;
                     None
                 } else {
                     Some(Implementor {
-                        text: imp.inner_impl().print(cx.cache(), false).to_string(),
+                        text: imp.inner_impl().print(cx.cache(), false, cx.depth()).to_string(),
                         synthetic: imp.inner_impl().synthetic,
                         types: collect_paths_for_type(imp.inner_impl().for_.clone(), cx.cache()),
                     })
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 0e975128628ac..48ad10031f8c4 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -216,8 +216,8 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
                 if let Some(ref tr) = impl_.trait_ {
                     debug!(
                         "impl {:#} for {:#} in {}",
-                        tr.print(&self.ctx.cache),
-                        impl_.for_.print(&self.ctx.cache),
+                        tr.print(&self.ctx.cache, 0),
+                        impl_.for_.print(&self.ctx.cache, 0),
                         filename,
                     );
 
@@ -228,7 +228,7 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
                     // inherent impls *can* be documented, and those docs show up, but in most
                     // cases it doesn't make sense, as all methods on a type are in one single
                     // impl block
-                    debug!("impl {:#} in {}", impl_.for_.print(&self.ctx.cache), filename);
+                    debug!("impl {:#} in {}", impl_.for_.print(&self.ctx.cache, 0), filename);
                 }
             }
             _ => {