diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 4cc81e860f09a..87ff2b896de09 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -9,6 +9,8 @@ use rustc_middle::middle::stability; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; +use std::borrow::Borrow; +use std::cell::{RefCell, RefMut}; use std::cmp::Ordering; use std::fmt; use std::rc::Rc; @@ -1098,65 +1100,104 @@ fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &cl write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) } +trait ItemTemplate<'a, 'cx: 'a> { + fn borrow_mut(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>); +} +fn item_template_render_assoc_items<'a: 'b, 'cx: 'a, 'b>( + this: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, mut cx) = this.borrow_mut(); + let def_id = item.item_id.expect_def_id(); + let v = render_assoc_items(&mut *cx, item, def_id, AssocItemRender::All); + write!(f, "{v}") + }) +} + +fn item_template_document_type_layout<'a: 'b, 'cx: 'a, 'b>( + this: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, mut cx) = this.borrow_mut(); + let def_id = item.item_id.expect_def_id(); + let v = document_type_layout(&mut *cx, def_id); + write!(f, "{v}") + }) +} + +fn item_template_document<'a: 'b, 'cx: 'a, 'b>( + this: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (item, mut cx) = this.borrow_mut(); + let v = document(&mut *cx, item, None, HeadingOffset::H2); + write!(f, "{v}") + }) +} + +fn item_template_render_attributes_in_pre<'a: 'b, 'cx: 'a, 'b>( + this: &'b impl ItemTemplate<'a, 'cx>, +) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let (it, cx) = this.borrow_mut(); + let v = render_attributes_in_pre(it, "", cx.tcx()); + write!(f, "{v}") + }) +} + fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) { - fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { - wrap_item(w, |w| { - write!( - w, - "{attrs}{}type {}{}{where_clause} = {type_};", - visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx), - it.name.unwrap(), - t.generics.print(cx), - where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline), - type_ = t.type_.print(cx), - attrs = render_attributes_in_pre(it, "", cx.tcx()), - ); - }); + #[derive(Template)] + #[template(path = "item_typedef.html")] + struct ItemTypedef<'a, 'cx> { + cx: RefCell<&'a mut Context<'cx>>, + it: &'a clean::Item, + t: &'a clean::Typedef, } - write_content(w, cx, it, t); + impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for ItemTypedef<'a, 'cx> { + fn borrow_mut(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) { + (&self.it, self.cx.borrow_mut()) + } + } - write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); + impl<'a, 'cx: 'a> ItemTypedef<'a, 'cx> { + fn render_typedef<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { + display_fn(move |f| { + let cx = self.cx.borrow_mut(); + let vis = self.it.visibility(cx.tcx()); + write!( + f, + "{}type {}{}{where_clause} = {type_};", + visibility_print_with_space(vis, self.it.item_id, *cx), + self.it.name.unwrap(), + self.t.generics.print(*cx), + where_clause = print_where_clause(&self.t.generics, *cx, 0, Ending::Newline), + type_ = self.t.type_.print(*cx), + )?; + Ok(()) + }) + } + } - let def_id = it.item_id.expect_def_id(); - // Render any items associated directly to this alias, as otherwise they - // won't be visible anywhere in the docs. It would be nice to also show - // associated items from the aliased type (see discussion in #32077), but - // we need #14072 to make sense of the generics. - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); - write!(w, "{}", document_type_layout(cx, def_id)); + ItemTypedef { cx: std::cell::RefCell::new(cx), it, t }.render_into(w).unwrap(); } fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) { #[derive(Template)] #[template(path = "item_union.html")] struct ItemUnion<'a, 'cx> { - cx: std::cell::RefCell<&'a mut Context<'cx>>, + cx: RefCell<&'a mut Context<'cx>>, it: &'a clean::Item, s: &'a clean::Union, } - impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { - fn render_assoc_items<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let def_id = self.it.item_id.expect_def_id(); - let mut cx = self.cx.borrow_mut(); - let v = render_assoc_items(*cx, self.it, def_id, AssocItemRender::All); - write!(f, "{v}") - }) - } - fn document_type_layout<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let def_id = self.it.item_id.expect_def_id(); - let cx = self.cx.borrow_mut(); - let v = document_type_layout(*cx, def_id); - write!(f, "{v}") - }) + impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for ItemUnion<'a, 'cx> { + fn borrow_mut(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) { + (&self.it, self.cx.borrow_mut()) } + } + + impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> { fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { display_fn(move |f| { let cx = self.cx.borrow_mut(); @@ -1164,22 +1205,6 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean: write!(f, "{v}") }) } - fn render_attributes_in_pre<'b>( - &'b self, - ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let tcx = self.cx.borrow().tcx(); - let v = render_attributes_in_pre(self.it, "", tcx); - write!(f, "{v}") - }) - } - fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> { - display_fn(move |f| { - let mut cx = self.cx.borrow_mut(); - let v = document(*cx, self.it, None, HeadingOffset::H2); - write!(f, "{v}") - }) - } fn document_field<'b>( &'b self, field: &'a clean::Item, diff --git a/src/librustdoc/html/templates/item_typedef.html b/src/librustdoc/html/templates/item_typedef.html new file mode 100644 index 0000000000000..56b4ac0ced0c0 --- /dev/null +++ b/src/librustdoc/html/templates/item_typedef.html @@ -0,0 +1,7 @@ +
+ {{ self::item_template_render_attributes_in_pre(self.borrow()) | safe }}
+ {{ self.render_typedef() | safe }}
+
+{{ self::item_template_document(self.borrow()) | safe }}
+{{ self::item_template_render_assoc_items(self.borrow()) | safe }}
+{{ self::item_template_document_type_layout(self.borrow()) | safe }}
diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html
index a01457971c178..c219670051332 100644
--- a/src/librustdoc/html/templates/item_union.html
+++ b/src/librustdoc/html/templates/item_union.html
@@ -1,8 +1,8 @@
- {{ self.render_attributes_in_pre() | safe }}
+ {{ self::item_template_render_attributes_in_pre(self.borrow()) | safe }}
{{ self.render_union() | safe }}
-{{ self.document() | safe }}
+{{ self::item_template_document(self.borrow()) | safe }}
{% if self.fields_iter().peek().is_some() %}