Skip to content

Commit b74d042

Browse files
authored
2 parents e8bc6e1 + 05824cd commit b74d042

16 files changed

+360
-110
lines changed

src/librustdoc/html/format.rs

-4
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,6 @@ impl Buffer {
107107
self.buffer
108108
}
109109

110-
pub(crate) fn insert_str(&mut self, idx: usize, s: &str) {
111-
self.buffer.insert_str(idx, s);
112-
}
113-
114110
pub(crate) fn push_str(&mut self, s: &str) {
115111
self.buffer.push_str(s);
116112
}

src/librustdoc/html/render/context.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,13 @@ pub(crate) struct Context<'tcx> {
6969
/// the source files are present in the html rendering, then this will be
7070
/// `true`.
7171
pub(crate) include_sources: bool,
72+
/// Collection of all types with notable traits referenced in the current module.
73+
pub(crate) types_with_notable_traits: FxHashSet<clean::Type>,
7274
}
7375

7476
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
7577
#[cfg(all(not(windows), target_arch = "x86_64", target_pointer_width = "64"))]
76-
rustc_data_structures::static_assert_size!(Context<'_>, 128);
78+
rustc_data_structures::static_assert_size!(Context<'_>, 160);
7779

7880
/// Shared mutable state used in [`Context`] and elsewhere.
7981
pub(crate) struct SharedContext<'tcx> {
@@ -532,6 +534,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
532534
deref_id_map: FxHashMap::default(),
533535
shared: Rc::new(scx),
534536
include_sources,
537+
types_with_notable_traits: FxHashSet::default(),
535538
};
536539

537540
if emit_crate {
@@ -560,6 +563,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
560563
id_map: IdMap::new(),
561564
shared: Rc::clone(&self.shared),
562565
include_sources: self.include_sources,
566+
types_with_notable_traits: FxHashSet::default(),
563567
}
564568
}
565569

@@ -803,6 +807,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
803807
}
804808
}
805809
}
810+
806811
Ok(())
807812
}
808813

src/librustdoc/html/render/mod.rs

+122-73
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ use rustc_span::{
5959
symbol::{sym, Symbol},
6060
BytePos, FileName, RealFileName,
6161
};
62-
use serde::ser::SerializeSeq;
62+
use serde::ser::{SerializeMap, SerializeSeq};
6363
use serde::{Serialize, Serializer};
6464

6565
use crate::clean::{self, ItemId, RenderedLink, SelfTy};
@@ -803,7 +803,7 @@ fn assoc_method(
803803
d: &clean::FnDecl,
804804
link: AssocItemLink<'_>,
805805
parent: ItemType,
806-
cx: &Context<'_>,
806+
cx: &mut Context<'_>,
807807
render_mode: RenderMode,
808808
) {
809809
let tcx = cx.tcx();
@@ -836,6 +836,8 @@ fn assoc_method(
836836
+ name.as_str().len()
837837
+ generics_len;
838838

839+
let notable_traits = d.output.as_return().and_then(|output| notable_traits_button(output, cx));
840+
839841
let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
840842
header_len += 4;
841843
let indent_str = " ";
@@ -861,9 +863,9 @@ fn assoc_method(
861863
name = name,
862864
generics = g.print(cx),
863865
decl = d.full_print(header_len, indent, cx),
864-
notable_traits = notable_traits_decl(d, cx),
866+
notable_traits = notable_traits.unwrap_or_default(),
865867
where_clause = print_where_clause(g, cx, indent, end_newline),
866-
)
868+
);
867869
}
868870

869871
/// Writes a span containing the versions at which an item became stable and/or const-stable. For
@@ -963,7 +965,7 @@ fn render_assoc_item(
963965
item: &clean::Item,
964966
link: AssocItemLink<'_>,
965967
parent: ItemType,
966-
cx: &Context<'_>,
968+
cx: &mut Context<'_>,
967969
render_mode: RenderMode,
968970
) {
969971
match &*item.kind {
@@ -1273,88 +1275,135 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
12731275
}
12741276
}
12751277

1276-
fn notable_traits_decl(decl: &clean::FnDecl, cx: &Context<'_>) -> String {
1277-
let mut out = Buffer::html();
1278+
pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> Option<String> {
1279+
let mut has_notable_trait = false;
1280+
1281+
let did = ty.def_id(cx.cache())?;
12781282

1279-
if let Some((did, ty)) = decl.output.as_return().and_then(|t| Some((t.def_id(cx.cache())?, t)))
1283+
// Box has pass-through impls for Read, Write, Iterator, and Future when the
1284+
// boxed type implements one of those. We don't want to treat every Box return
1285+
// as being notably an Iterator (etc), though, so we exempt it. Pin has the same
1286+
// issue, with a pass-through impl for Future.
1287+
if Some(did) == cx.tcx().lang_items().owned_box()
1288+
|| Some(did) == cx.tcx().lang_items().pin_type()
12801289
{
1281-
// Box has pass-through impls for Read, Write, Iterator, and Future when the
1282-
// boxed type implements one of those. We don't want to treat every Box return
1283-
// as being notably an Iterator (etc), though, so we exempt it. Pin has the same
1284-
// issue, with a pass-through impl for Future.
1285-
if Some(did) == cx.tcx().lang_items().owned_box()
1286-
|| Some(did) == cx.tcx().lang_items().pin_type()
1287-
{
1288-
return "".to_string();
1289-
}
1290-
if let Some(impls) = cx.cache().impls.get(&did) {
1291-
for i in impls {
1292-
let impl_ = i.inner_impl();
1293-
if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache())
1290+
return None;
1291+
}
1292+
1293+
if let Some(impls) = cx.cache().impls.get(&did) {
1294+
for i in impls {
1295+
let impl_ = i.inner_impl();
1296+
if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache()) {
1297+
// Two different types might have the same did,
1298+
// without actually being the same.
1299+
continue;
1300+
}
1301+
if let Some(trait_) = &impl_.trait_ {
1302+
let trait_did = trait_.def_id();
1303+
1304+
if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable_trait(cx.tcx()))
12941305
{
1295-
// Two different types might have the same did,
1296-
// without actually being the same.
1297-
continue;
1306+
has_notable_trait = true;
1307+
}
1308+
}
1309+
}
1310+
}
1311+
1312+
if has_notable_trait {
1313+
cx.types_with_notable_traits.insert(ty.clone());
1314+
Some(format!(
1315+
"<span class=\"notable-traits\" data-ty=\"{ty}\">\
1316+
<span class=\"notable-traits-tooltip\">ⓘ</span>\
1317+
</span>",
1318+
ty = Escape(&format!("{:#}", ty.print(cx))),
1319+
))
1320+
} else {
1321+
None
1322+
}
1323+
}
1324+
1325+
fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
1326+
let mut out = Buffer::html();
1327+
1328+
let did = ty.def_id(cx.cache()).expect("notable_traits_button already checked this");
1329+
1330+
let impls = cx.cache().impls.get(&did).expect("notable_traits_button already checked this");
1331+
1332+
for i in impls {
1333+
let impl_ = i.inner_impl();
1334+
if !impl_.for_.without_borrowed_ref().is_same(ty.without_borrowed_ref(), cx.cache()) {
1335+
// Two different types might have the same did,
1336+
// without actually being the same.
1337+
continue;
1338+
}
1339+
if let Some(trait_) = &impl_.trait_ {
1340+
let trait_did = trait_.def_id();
1341+
1342+
if cx.cache().traits.get(&trait_did).map_or(false, |t| t.is_notable_trait(cx.tcx())) {
1343+
if out.is_empty() {
1344+
write!(
1345+
&mut out,
1346+
"<h3 class=\"notable\">Notable traits for <code>{}</code></h3>\
1347+
<pre class=\"content\"><code>",
1348+
impl_.for_.print(cx)
1349+
);
12981350
}
1299-
if let Some(trait_) = &impl_.trait_ {
1300-
let trait_did = trait_.def_id();
1301-
1302-
if cx
1303-
.cache()
1304-
.traits
1305-
.get(&trait_did)
1306-
.map_or(false, |t| t.is_notable_trait(cx.tcx()))
1307-
{
1308-
if out.is_empty() {
1309-
write!(
1310-
&mut out,
1311-
"<span class=\"notable\">Notable traits for {}</span>\
1312-
<code class=\"content\">",
1313-
impl_.for_.print(cx)
1314-
);
1315-
}
13161351

1317-
//use the "where" class here to make it small
1318-
write!(
1352+
//use the "where" class here to make it small
1353+
write!(
1354+
&mut out,
1355+
"<span class=\"where fmt-newline\">{}</span>",
1356+
impl_.print(false, cx)
1357+
);
1358+
for it in &impl_.items {
1359+
if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
1360+
out.push_str("<span class=\"where fmt-newline\"> ");
1361+
let empty_set = FxHashSet::default();
1362+
let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set);
1363+
assoc_type(
13191364
&mut out,
1320-
"<span class=\"where fmt-newline\">{}</span>",
1321-
impl_.print(false, cx)
1365+
it,
1366+
&tydef.generics,
1367+
&[], // intentionally leaving out bounds
1368+
Some(&tydef.type_),
1369+
src_link,
1370+
0,
1371+
cx,
13221372
);
1323-
for it in &impl_.items {
1324-
if let clean::AssocTypeItem(ref tydef, ref _bounds) = *it.kind {
1325-
out.push_str("<span class=\"where fmt-newline\"> ");
1326-
let empty_set = FxHashSet::default();
1327-
let src_link =
1328-
AssocItemLink::GotoSource(trait_did.into(), &empty_set);
1329-
assoc_type(
1330-
&mut out,
1331-
it,
1332-
&tydef.generics,
1333-
&[], // intentionally leaving out bounds
1334-
Some(&tydef.type_),
1335-
src_link,
1336-
0,
1337-
cx,
1338-
);
1339-
out.push_str(";</span>");
1340-
}
1341-
}
1373+
out.push_str(";</span>");
13421374
}
13431375
}
13441376
}
13451377
}
13461378
}
1347-
1348-
if !out.is_empty() {
1349-
out.insert_str(
1350-
0,
1351-
"<span class=\"notable-traits\"><span class=\"notable-traits-tooltip\">ⓘ\
1352-
<span class=\"notable-traits-tooltiptext\"><span class=\"docblock\">",
1353-
);
1354-
out.push_str("</code></span></span></span></span>");
1379+
if out.is_empty() {
1380+
write!(&mut out, "</code></pre>",);
13551381
}
13561382

1357-
out.into_inner()
1383+
(format!("{:#}", ty.print(cx)), out.into_inner())
1384+
}
1385+
1386+
pub(crate) fn notable_traits_json<'a>(
1387+
tys: impl Iterator<Item = &'a clean::Type>,
1388+
cx: &Context<'_>,
1389+
) -> String {
1390+
let mut mp: Vec<(String, String)> = tys.map(|ty| notable_traits_decl(ty, cx)).collect();
1391+
mp.sort_by(|(name1, _html1), (name2, _html2)| name1.cmp(name2));
1392+
struct NotableTraitsMap(Vec<(String, String)>);
1393+
impl Serialize for NotableTraitsMap {
1394+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1395+
where
1396+
S: Serializer,
1397+
{
1398+
let mut map = serializer.serialize_map(Some(self.0.len()))?;
1399+
for item in &self.0 {
1400+
map.serialize_entry(&item.0, &item.1)?;
1401+
}
1402+
map.end()
1403+
}
1404+
}
1405+
serde_json::to_string(&NotableTraitsMap(mp))
1406+
.expect("serialize (string, string) -> json object cannot fail")
13581407
}
13591408

13601409
#[derive(Clone, Copy, Debug)]

src/librustdoc/html/render/print_item.rs

+19-5
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ use std::rc::Rc;
1717

1818
use super::{
1919
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
20-
item_ty_to_section, notable_traits_decl, render_all_impls, render_assoc_item,
21-
render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl,
22-
render_rightside, render_stability_since_raw, AssocItemLink, Context, ImplRenderingParameters,
20+
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
21+
render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
22+
render_impl, render_rightside, render_stability_since_raw, AssocItemLink, Context,
23+
ImplRenderingParameters,
2324
};
2425
use crate::clean;
2526
use crate::config::ModuleSorting;
@@ -183,6 +184,16 @@ pub(super) fn print_item(
183184
unreachable!();
184185
}
185186
}
187+
188+
// Render notable-traits.js used for all methods in this module.
189+
if !cx.types_with_notable_traits.is_empty() {
190+
write!(
191+
buf,
192+
r#"<script type="text/json" id="notable-traits-data">{}</script>"#,
193+
notable_traits_json(cx.types_with_notable_traits.iter(), cx)
194+
);
195+
cx.types_with_notable_traits.clear();
196+
}
186197
}
187198

188199
/// For large structs, enums, unions, etc, determine whether to hide their fields
@@ -516,6 +527,9 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
516527
+ name.as_str().len()
517528
+ generics_len;
518529

530+
let notable_traits =
531+
f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
532+
519533
wrap_into_item_decl(w, |w| {
520534
wrap_item(w, "fn", |w| {
521535
render_attributes_in_pre(w, it, "");
@@ -533,11 +547,11 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
533547
generics = f.generics.print(cx),
534548
where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
535549
decl = f.decl.full_print(header_len, 0, cx),
536-
notable_traits = notable_traits_decl(&f.decl, cx),
550+
notable_traits = notable_traits.unwrap_or_default(),
537551
);
538552
});
539553
});
540-
document(w, cx, it, None, HeadingOffset::H2)
554+
document(w, cx, it, None, HeadingOffset::H2);
541555
}
542556

543557
fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) {

src/librustdoc/html/static/css/noscript.css

+6
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,9 @@ nav.sub {
2222
.source .sidebar {
2323
display: none;
2424
}
25+
26+
.notable-traits {
27+
/* layout requires javascript
28+
https://github.com/rust-lang/rust/issues/102576 */
29+
display: none;
30+
}

0 commit comments

Comments
 (0)