@@ -40,6 +40,7 @@ mod span_map;
40
40
mod type_layout;
41
41
mod write_shared;
42
42
43
+ use std::borrow::Cow;
43
44
use std::collections::VecDeque;
44
45
use std::fmt::{self, Display as _, Write};
45
46
use std::iter::Peekable;
@@ -99,6 +100,19 @@ enum AssocItemRender<'a> {
99
100
DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool },
100
101
}
101
102
103
+ impl AssocItemRender<'_> {
104
+ fn render_mode(&self) -> RenderMode {
105
+ match self {
106
+ Self::All => RenderMode::Normal,
107
+ &Self::DerefFor { deref_mut_, .. } => RenderMode::ForDeref { mut_: deref_mut_ },
108
+ }
109
+ }
110
+
111
+ fn class(&self) -> Option<&'static str> {
112
+ if let Self::DerefFor { .. } = self { Some("impl-items") } else { None }
113
+ }
114
+ }
115
+
102
116
/// For different handling of associated items from the Deref target of a type rather than the type
103
117
/// itself.
104
118
#[derive(Copy, Clone, PartialEq)]
@@ -1211,7 +1225,7 @@ impl<'a> AssocItemLink<'a> {
1211
1225
}
1212
1226
1213
1227
fn write_section_heading(
1214
- title: &str ,
1228
+ title: impl fmt::Display ,
1215
1229
id: &str,
1216
1230
extra_class: Option<&str>,
1217
1231
extra: impl fmt::Display,
@@ -1231,7 +1245,7 @@ fn write_section_heading(
1231
1245
})
1232
1246
}
1233
1247
1234
- fn write_impl_section_heading(title: &str , id: &str) -> impl fmt::Display {
1248
+ fn write_impl_section_heading(title: impl fmt::Display , id: &str) -> impl fmt::Display {
1235
1249
write_section_heading(title, id, None, "")
1236
1250
}
1237
1251
@@ -1308,20 +1322,17 @@ fn render_assoc_items_inner(
1308
1322
let (mut non_trait, traits): (Vec<_>, _) =
1309
1323
v.iter().partition(|i| i.inner_impl().trait_.is_none());
1310
1324
if !non_trait.is_empty() {
1311
- let mut close_tags = <Vec<&str>>::with_capacity(1);
1312
- let mut tmp_buf = String::new();
1313
- let (render_mode, id, class_html) = match what {
1314
- AssocItemRender::All => {
1315
- write_str(
1316
- &mut tmp_buf,
1317
- format_args!(
1318
- "{}",
1319
- write_impl_section_heading("Implementations", "implementations")
1320
- ),
1321
- );
1322
- (RenderMode::Normal, "implementations-list".to_owned(), "")
1323
- }
1324
- AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
1325
+ let render_mode = what.render_mode();
1326
+ let class_html = what
1327
+ .class()
1328
+ .map(|class| fmt::from_fn(move |f| write!(f, r#" class="{class}""#)))
1329
+ .maybe_display();
1330
+ let (section_heading, id) = match what {
1331
+ AssocItemRender::All => (
1332
+ Either::Left(write_impl_section_heading("Implementations", "implementations")),
1333
+ Cow::Borrowed("implementations-list"),
1334
+ ),
1335
+ AssocItemRender::DerefFor { trait_, type_, .. } => {
1325
1336
let id =
1326
1337
cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
1327
1338
// the `impls.get` above only looks at the outermost type,
@@ -1335,25 +1346,27 @@ fn render_assoc_items_inner(
1335
1346
type_.is_doc_subtype_of(&impl_.inner_impl().for_, &cx.shared.cache)
1336
1347
});
1337
1348
let derived_id = cx.derive_id(&id);
1338
- close_tags.push("</details>");
1339
- write_str(
1340
- &mut tmp_buf,
1341
- format_args!(
1342
- "<details class=\"toggle big-toggle\" open><summary>{}</summary>",
1343
- write_impl_section_heading(
1344
- &format!(
1345
- "<span>Methods from {trait_}<Target = {type_}></span>",
1346
- trait_ = trait_.print(cx),
1347
- type_ = type_.print(cx),
1348
- ),
1349
- &id,
1350
- )
1351
- ),
1352
- );
1353
1349
if let Some(def_id) = type_.def_id(cx.cache()) {
1354
- cx.deref_id_map.borrow_mut().insert(def_id, id);
1350
+ cx.deref_id_map.borrow_mut().insert(def_id, id.clone() );
1355
1351
}
1356
- (RenderMode::ForDeref { mut_: deref_mut_ }, derived_id, r#" class="impl-items""#)
1352
+ (
1353
+ Either::Right(fmt::from_fn(move |f| {
1354
+ write!(
1355
+ f,
1356
+ "<details class=\"toggle big-toggle\" open><summary>{}</summary>",
1357
+ write_impl_section_heading(
1358
+ fmt::from_fn(|f| write!(
1359
+ f,
1360
+ "<span>Methods from {trait_}<Target = {type_}></span>",
1361
+ trait_ = trait_.print(cx),
1362
+ type_ = type_.print(cx),
1363
+ )),
1364
+ &id,
1365
+ )
1366
+ )
1367
+ })),
1368
+ Cow::Owned(derived_id),
1369
+ )
1357
1370
}
1358
1371
};
1359
1372
let mut impls_buf = String::new();
@@ -1381,10 +1394,14 @@ fn render_assoc_items_inner(
1381
1394
);
1382
1395
}
1383
1396
if !impls_buf.is_empty() {
1384
- write!(w, "{tmp_buf}<div id=\"{id}\"{class_html}>{impls_buf}</div>").unwrap();
1385
- for tag in close_tags.into_iter().rev() {
1386
- w.write_str(tag).unwrap();
1387
- }
1397
+ write!(
1398
+ w,
1399
+ "{section_heading}<div id=\"{id}\"{class_html}>{impls_buf}</div>{}",
1400
+ matches!(what, AssocItemRender::DerefFor { .. })
1401
+ .then_some("</details>")
1402
+ .maybe_display(),
1403
+ )
1404
+ .unwrap();
1388
1405
}
1389
1406
}
1390
1407
0 commit comments