Skip to content

Commit 3fd362a

Browse files
rustdoc: Strikethrough deprecated items in sidebar
1 parent b9ad9b7 commit 3fd362a

File tree

5 files changed

+124
-49
lines changed

5 files changed

+124
-49
lines changed

src/librustdoc/clean/types.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_hir::lang_items::LangItem;
2222
use rustc_hir::{BodyId, Mutability};
2323
use rustc_hir_analysis::check::intrinsic::intrinsic_operation_unsafety;
2424
use rustc_index::IndexVec;
25+
use rustc_middle::middle::stability;
2526
use rustc_middle::ty::fast_reject::SimplifiedType;
2627
use rustc_middle::ty::{self, TyCtxt, Visibility};
2728
use rustc_resolve::rustdoc::{add_doc_fragment, attrs_to_doc_fragments, inner_docs, DocFragment};
@@ -369,6 +370,13 @@ impl Item {
369370
self.def_id().and_then(|did| tcx.lookup_deprecation(did))
370371
}
371372

373+
pub(crate) fn is_deprecated(&self, tcx: TyCtxt<'_>) -> bool {
374+
match self.deprecation(tcx) {
375+
Some(depr) => stability::deprecation_in_effect(&depr),
376+
None => false,
377+
}
378+
}
379+
372380
pub(crate) fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
373381
self.item_id
374382
.as_def_id()

src/librustdoc/html/render/context.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use std::path::{Path, PathBuf};
55
use std::rc::Rc;
66
use std::sync::mpsc::{channel, Receiver};
77

8+
use serde::Serialize;
9+
810
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
911
use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
1012
use rustc_middle::ty::TyCtxt;
@@ -149,6 +151,13 @@ impl SharedContext<'_> {
149151
}
150152
}
151153

154+
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize)]
155+
struct SidebarEntry {
156+
name: String,
157+
#[serde(skip_serializing_if = "std::ops::Not::not")]
158+
is_deprecated: bool,
159+
}
160+
152161
impl<'tcx> Context<'tcx> {
153162
pub(crate) fn tcx(&self) -> TyCtxt<'tcx> {
154163
self.shared.tcx
@@ -273,7 +282,9 @@ impl<'tcx> Context<'tcx> {
273282
}
274283

275284
/// Construct a map of items shown in the sidebar to a plain-text summary of their docs.
276-
fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<String>> {
285+
fn build_sidebar_items(&self, m: &clean::Module) -> BTreeMap<String, Vec<SidebarEntry>> {
286+
let tcx = self.tcx();
287+
277288
// BTreeMap instead of HashMap to get a sorted output
278289
let mut map: BTreeMap<_, Vec<_>> = BTreeMap::new();
279290
let mut inserted: FxHashMap<ItemType, FxHashSet<Symbol>> = FxHashMap::default();
@@ -291,7 +302,9 @@ impl<'tcx> Context<'tcx> {
291302
if inserted.entry(short).or_default().insert(myname) {
292303
let short = short.to_string();
293304
let myname = myname.to_string();
294-
map.entry(short).or_default().push(myname);
305+
map.entry(short)
306+
.or_default()
307+
.push(SidebarEntry { name: myname, is_deprecated: item.is_deprecated(tcx) });
295308
}
296309
}
297310

src/librustdoc/html/render/sidebar.rs

Lines changed: 85 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,20 @@ pub(crate) struct Link<'a> {
6464
name: Cow<'a, str>,
6565
/// The id of an anchor within the page (without a `#` prefix)
6666
href: Cow<'a, str>,
67+
/// Whether the item is deprecated
68+
is_deprecated: bool,
6769
}
6870

6971
impl<'a> Link<'a> {
70-
pub fn new(href: impl Into<Cow<'a, str>>, name: impl Into<Cow<'a, str>>) -> Self {
71-
Self { href: href.into(), name: name.into() }
72+
pub fn new(
73+
href: impl Into<Cow<'a, str>>,
74+
name: impl Into<Cow<'a, str>>,
75+
deprecated: bool,
76+
) -> Self {
77+
Self { href: href.into(), name: name.into(), is_deprecated: deprecated }
7278
}
7379
pub fn empty() -> Link<'static> {
74-
Link::new("", "")
80+
Link::new("", "", false)
7581
}
7682
}
7783

@@ -124,12 +130,14 @@ pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buf
124130
sidebar.render_into(buffer).unwrap();
125131
}
126132

127-
fn get_struct_fields_name<'a>(fields: &'a [clean::Item]) -> Vec<Link<'a>> {
133+
fn get_struct_fields_name<'a>(fields: &'a [clean::Item], tcx: TyCtxt<'_>) -> Vec<Link<'a>> {
128134
let mut fields = fields
129135
.iter()
130136
.filter(|f| matches!(*f.kind, clean::StructFieldItem(..)))
131137
.filter_map(|f| {
132-
f.name.as_ref().map(|name| Link::new(format!("structfield.{name}"), name.as_str()))
138+
f.name.as_ref().map(|name| {
139+
Link::new(format!("structfield.{name}"), name.as_str(), f.is_deprecated(tcx))
140+
})
133141
})
134142
.collect::<Vec<Link<'a>>>();
135143
fields.sort();
@@ -141,15 +149,15 @@ fn sidebar_struct<'a>(
141149
it: &'a clean::Item,
142150
s: &'a clean::Struct,
143151
) -> Vec<LinkBlock<'a>> {
144-
let fields = get_struct_fields_name(&s.fields);
152+
let fields = get_struct_fields_name(&s.fields, cx.tcx());
145153
let field_name = match s.ctor_kind {
146154
Some(CtorKind::Fn) => Some("Tuple Fields"),
147155
None => Some("Fields"),
148156
_ => None,
149157
};
150158
let mut items = vec![];
151159
if let Some(name) = field_name {
152-
items.push(LinkBlock::new(Link::new("fields", name), fields));
160+
items.push(LinkBlock::new(Link::new("fields", name, false), fields));
153161
}
154162
sidebar_assoc_items(cx, it, &mut items);
155163
items
@@ -164,35 +172,39 @@ fn sidebar_trait<'a>(
164172
items: &'a [clean::Item],
165173
filt: impl Fn(&clean::Item) -> bool,
166174
ty: &str,
175+
tcx: TyCtxt<'_>,
167176
) -> Vec<Link<'a>> {
168177
let mut res = items
169178
.iter()
170179
.filter_map(|m: &clean::Item| match m.name {
171-
Some(ref name) if filt(m) => Some(Link::new(format!("{ty}.{name}"), name.as_str())),
180+
Some(ref name) if filt(m) => {
181+
Some(Link::new(format!("{ty}.{name}"), name.as_str(), m.is_deprecated(tcx)))
182+
}
172183
_ => None,
173184
})
174185
.collect::<Vec<Link<'a>>>();
175186
res.sort();
176187
res
177188
}
178189

179-
let req_assoc = filter_items(&t.items, |m| m.is_ty_associated_type(), "associatedtype");
180-
let prov_assoc = filter_items(&t.items, |m| m.is_associated_type(), "associatedtype");
190+
let tcx = cx.tcx();
191+
192+
let req_assoc = filter_items(&t.items, |m| m.is_ty_associated_type(), "associatedtype", tcx);
193+
let prov_assoc = filter_items(&t.items, |m| m.is_associated_type(), "associatedtype", tcx);
181194
let req_assoc_const =
182-
filter_items(&t.items, |m| m.is_ty_associated_const(), "associatedconstant");
195+
filter_items(&t.items, |m| m.is_ty_associated_const(), "associatedconstant", tcx);
183196
let prov_assoc_const =
184-
filter_items(&t.items, |m| m.is_associated_const(), "associatedconstant");
185-
let req_method = filter_items(&t.items, |m| m.is_ty_method(), "tymethod");
186-
let prov_method = filter_items(&t.items, |m| m.is_method(), "method");
197+
filter_items(&t.items, |m| m.is_associated_const(), "associatedconstant", tcx);
198+
let req_method = filter_items(&t.items, |m| m.is_ty_method(), "tymethod", tcx);
199+
let prov_method = filter_items(&t.items, |m| m.is_method(), "method", tcx);
187200
let mut foreign_impls = vec![];
188201
if let Some(implementors) = cx.cache().implementors.get(&it.item_id.expect_def_id()) {
189-
foreign_impls.extend(
190-
implementors
191-
.iter()
192-
.filter(|i| !i.is_on_local_type(cx))
193-
.filter_map(|i| super::extract_for_impl_name(&i.impl_item, cx))
194-
.map(|(name, id)| Link::new(id, name)),
195-
);
202+
foreign_impls.extend(implementors.iter().filter(|i| !i.is_on_local_type(cx)).filter_map(
203+
|i| {
204+
super::extract_for_impl_name(&i.impl_item, cx)
205+
.map(|(name, id)| Link::new(id, name, i.impl_item.is_deprecated(tcx)))
206+
},
207+
));
196208
foreign_impls.sort();
197209
}
198210

@@ -206,12 +218,16 @@ fn sidebar_trait<'a>(
206218
("foreign-impls", "Implementations on Foreign Types", foreign_impls),
207219
]
208220
.into_iter()
209-
.map(|(id, title, items)| LinkBlock::new(Link::new(id, title), items))
221+
.map(|(id, title, items)| LinkBlock::new(Link::new(id, title, false), items))
210222
.collect();
211223
sidebar_assoc_items(cx, it, &mut blocks);
212-
blocks.push(LinkBlock::forced(Link::new("implementors", "Implementors")));
224+
blocks.push(LinkBlock::forced(Link::new("implementors", "Implementors", false)));
213225
if t.is_auto(cx.tcx()) {
214-
blocks.push(LinkBlock::forced(Link::new("synthetic-implementors", "Auto Implementors")));
226+
blocks.push(LinkBlock::forced(Link::new(
227+
"synthetic-implementors",
228+
"Auto Implementors",
229+
false,
230+
)));
215231
}
216232
blocks
217233
}
@@ -241,8 +257,8 @@ fn sidebar_union<'a>(
241257
it: &'a clean::Item,
242258
u: &'a clean::Union,
243259
) -> Vec<LinkBlock<'a>> {
244-
let fields = get_struct_fields_name(&u.fields);
245-
let mut items = vec![LinkBlock::new(Link::new("fields", "Fields"), fields)];
260+
let fields = get_struct_fields_name(&u.fields, cx.tcx());
261+
let mut items = vec![LinkBlock::new(Link::new("fields", "Fields", false), fields)];
246262
sidebar_assoc_items(cx, it, &mut items);
247263
items
248264
}
@@ -253,6 +269,7 @@ fn sidebar_assoc_items<'a>(
253269
it: &'a clean::Item,
254270
links: &mut Vec<LinkBlock<'a>>,
255271
) {
272+
let tcx = cx.tcx();
256273
let did = it.item_id.expect_def_id();
257274
let cache = cx.cache();
258275

@@ -267,7 +284,7 @@ fn sidebar_assoc_items<'a>(
267284
assoc_consts.extend(
268285
v.iter()
269286
.filter(|i| i.inner_impl().trait_.is_none())
270-
.flat_map(|i| get_associated_constants(i.inner_impl(), used_links_bor)),
287+
.flat_map(|i| get_associated_constants(i.inner_impl(), used_links_bor, tcx)),
271288
);
272289
// We want links' order to be reproducible so we don't use unstable sort.
273290
assoc_consts.sort();
@@ -311,8 +328,11 @@ fn sidebar_assoc_items<'a>(
311328
};
312329

313330
let mut blocks = vec![
314-
LinkBlock::new(Link::new("implementations", "Associated Constants"), assoc_consts),
315-
LinkBlock::new(Link::new("implementations", "Methods"), methods),
331+
LinkBlock::new(
332+
Link::new("implementations", "Associated Constants", false),
333+
assoc_consts,
334+
),
335+
LinkBlock::new(Link::new("implementations", "Methods", false), methods),
316336
];
317337
blocks.append(&mut deref_methods);
318338
blocks.extend([concrete, synthetic, blanket]);
@@ -329,13 +349,16 @@ fn sidebar_deref_methods<'a>(
329349
used_links: &mut FxHashSet<String>,
330350
) {
331351
let c = cx.cache();
352+
let tcx = cx.tcx();
332353

333354
debug!("found Deref: {:?}", impl_);
334-
if let Some((target, real_target)) =
355+
if let Some((target, real_target, target_is_deprecated)) =
335356
impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
336357
clean::AssocTypeItem(box ref t, _) => Some(match *t {
337-
clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_),
338-
_ => (&t.type_, &t.type_),
358+
clean::Typedef { item_type: Some(ref type_), .. } => {
359+
(type_, &t.type_, item.is_deprecated(tcx))
360+
}
361+
_ => (&t.type_, &t.type_, item.is_deprecated(tcx)),
339362
}),
340363
_ => None,
341364
})
@@ -349,7 +372,7 @@ fn sidebar_deref_methods<'a>(
349372
// Avoid infinite cycles
350373
return;
351374
}
352-
let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait());
375+
let deref_mut = v.iter().any(|i| i.trait_did() == tcx.lang_items().deref_mut_trait());
353376
let inner_impl = target
354377
.def_id(c)
355378
.or_else(|| {
@@ -361,7 +384,7 @@ fn sidebar_deref_methods<'a>(
361384
let mut ret = impls
362385
.iter()
363386
.filter(|i| i.inner_impl().trait_.is_none())
364-
.flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx()))
387+
.flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, tcx))
365388
.collect::<Vec<_>>();
366389
if !ret.is_empty() {
367390
let id = if let Some(target_def_id) = real_target.def_id(c) {
@@ -381,7 +404,7 @@ fn sidebar_deref_methods<'a>(
381404
);
382405
// We want links' order to be reproducible so we don't use unstable sort.
383406
ret.sort();
384-
out.push(LinkBlock::new(Link::new(id, title), ret));
407+
out.push(LinkBlock::new(Link::new(id, title, target_is_deprecated), ret));
385408
}
386409
}
387410

@@ -392,7 +415,7 @@ fn sidebar_deref_methods<'a>(
392415
i.inner_impl()
393416
.trait_
394417
.as_ref()
395-
.map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait())
418+
.map(|t| Some(t.def_id()) == tcx.lang_items().deref_trait())
396419
.unwrap_or(false)
397420
})
398421
{
@@ -413,14 +436,18 @@ fn sidebar_enum<'a>(
413436
it: &'a clean::Item,
414437
e: &'a clean::Enum,
415438
) -> Vec<LinkBlock<'a>> {
439+
let tcx = cx.tcx();
416440
let mut variants = e
417441
.variants()
418-
.filter_map(|v| v.name)
419-
.map(|name| Link::new(format!("variant.{name}"), name.to_string()))
442+
.filter_map(|v| {
443+
v.name.map(|name| {
444+
Link::new(format!("variant.{name}"), name.to_string(), v.is_deprecated(tcx))
445+
})
446+
})
420447
.collect::<Vec<_>>();
421448
variants.sort_unstable();
422449

423-
let mut items = vec![LinkBlock::new(Link::new("variants", "Variants"), variants)];
450+
let mut items = vec![LinkBlock::new(Link::new("variants", "Variants", false), variants)];
424451
sidebar_assoc_items(cx, it, &mut items);
425452
items
426453
}
@@ -432,7 +459,7 @@ pub(crate) fn sidebar_module_like(
432459
.iter()
433460
.copied()
434461
.filter(|sec| item_sections_in_use.contains(sec))
435-
.map(|sec| Link::new(sec.id(), sec.name()))
462+
.map(|sec| Link::new(sec.id(), sec.name(), false))
436463
.collect();
437464
LinkBlock::new(Link::empty(), item_sections)
438465
}
@@ -470,6 +497,7 @@ fn sidebar_render_assoc_items(
470497
synthetic: Vec<&Impl>,
471498
blanket_impl: Vec<&Impl>,
472499
) -> [LinkBlock<'static>; 3] {
500+
let tcx = cx.tcx();
473501
let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| {
474502
let mut links = FxHashSet::default();
475503

@@ -484,7 +512,11 @@ fn sidebar_render_assoc_items(
484512
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
485513
ty::ImplPolarity::Negative => "!",
486514
};
487-
let generated = Link::new(encoded, format!("{prefix}{:#}", trait_.print(cx)));
515+
let generated = Link::new(
516+
encoded,
517+
format!("{prefix}{:#}", trait_.print(cx)),
518+
it.impl_item.is_deprecated(tcx),
519+
);
488520
if links.insert(generated.clone()) { Some(generated) } else { None }
489521
})
490522
.collect::<Vec<Link<'static>>>();
@@ -496,12 +528,18 @@ fn sidebar_render_assoc_items(
496528
let synthetic = format_impls(synthetic, id_map);
497529
let blanket = format_impls(blanket_impl, id_map);
498530
[
499-
LinkBlock::new(Link::new("trait-implementations", "Trait Implementations"), concrete),
500531
LinkBlock::new(
501-
Link::new("synthetic-implementations", "Auto Trait Implementations"),
532+
Link::new("trait-implementations", "Trait Implementations", false),
533+
concrete,
534+
),
535+
LinkBlock::new(
536+
Link::new("synthetic-implementations", "Auto Trait Implementations", false),
502537
synthetic,
503538
),
504-
LinkBlock::new(Link::new("blanket-implementations", "Blanket Implementations"), blanket),
539+
LinkBlock::new(
540+
Link::new("blanket-implementations", "Blanket Implementations", false),
541+
blanket,
542+
),
505543
]
506544
}
507545

@@ -531,6 +569,7 @@ fn get_methods<'a>(
531569
Some(Link::new(
532570
get_next_url(used_links, format!("{}.{}", ItemType::Method, name)),
533571
name.as_str(),
572+
item.is_deprecated(tcx),
534573
))
535574
} else {
536575
None
@@ -544,13 +583,15 @@ fn get_methods<'a>(
544583
fn get_associated_constants<'a>(
545584
i: &'a clean::Impl,
546585
used_links: &mut FxHashSet<String>,
586+
tcx: TyCtxt<'_>,
547587
) -> Vec<Link<'a>> {
548588
i.items
549589
.iter()
550590
.filter_map(|item| match item.name {
551591
Some(ref name) if !name.is_empty() && item.is_associated_const() => Some(Link::new(
552592
get_next_url(used_links, format!("{}.{}", ItemType::AssocConst, name)),
553593
name.as_str(),
594+
item.is_deprecated(tcx),
554595
)),
555596
_ => None,
556597
})

0 commit comments

Comments
 (0)