Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 3b50a4e

Browse files
committed
Use DefIds instead of names in UrlFragment
This is the next step in computing more "semantic" information during intra-doc link collection and then doing rendering all at the end.
1 parent f89e2dd commit 3b50a4e

File tree

2 files changed

+49
-46
lines changed

2 files changed

+49
-46
lines changed

src/librustdoc/clean/types.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::cell::RefCell;
22
use std::default::Default;
3-
use std::fmt::Write;
43
use std::hash::Hash;
54
use std::lazy::SyncOnceCell as OnceCell;
65
use std::path::PathBuf;
@@ -496,7 +495,7 @@ impl Item {
496495
if let Ok((mut href, ..)) = href(*did, cx) {
497496
debug!(?href);
498497
if let Some(ref fragment) = *fragment {
499-
write!(href, "{}", fragment).unwrap()
498+
fragment.render(&mut href, cx.tcx()).unwrap()
500499
}
501500
Some(RenderedLink {
502501
original_text: s.clone(),

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_hir::def::{
1313
PerNS,
1414
};
1515
use rustc_hir::def_id::{CrateNum, DefId};
16-
use rustc_middle::ty::{Ty, TyCtxt};
16+
use rustc_middle::ty::{DefIdTree, Ty, TyCtxt};
1717
use rustc_middle::{bug, span_bug, ty};
1818
use rustc_resolve::ParentScope;
1919
use rustc_session::lint::Lint;
@@ -27,6 +27,7 @@ use pulldown_cmark::LinkType;
2727
use std::borrow::Cow;
2828
use std::cell::Cell;
2929
use std::convert::{TryFrom, TryInto};
30+
use std::fmt::Write;
3031
use std::mem;
3132
use std::ops::Range;
3233

@@ -240,53 +241,61 @@ enum AnchorFailure {
240241

241242
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
242243
crate enum UrlFragment {
243-
Method(Symbol),
244-
TyMethod(Symbol),
245-
AssociatedConstant(Symbol),
246-
AssociatedType(Symbol),
244+
Def(FragmentKind, DefId),
245+
UserWritten(String),
246+
}
247247

248-
StructField(Symbol),
249-
Variant(Symbol),
250-
VariantField { variant: Symbol, field: Symbol },
248+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
249+
crate enum FragmentKind {
250+
Method,
251+
TyMethod,
252+
AssociatedConstant,
253+
AssociatedType,
251254

252-
UserWritten(String),
255+
StructField,
256+
Variant,
257+
VariantField,
253258
}
254259

255260
impl UrlFragment {
256261
/// Create a fragment for an associated item.
257262
///
258263
/// `is_prototype` is whether this associated item is a trait method
259264
/// without a default definition.
260-
fn from_assoc_item(name: Symbol, kind: ty::AssocKind, is_prototype: bool) -> Self {
265+
fn from_assoc_item(def_id: DefId, kind: ty::AssocKind, is_prototype: bool) -> Self {
261266
match kind {
262267
ty::AssocKind::Fn => {
263268
if is_prototype {
264-
UrlFragment::TyMethod(name)
269+
UrlFragment::Def(FragmentKind::TyMethod, def_id)
265270
} else {
266-
UrlFragment::Method(name)
271+
UrlFragment::Def(FragmentKind::Method, def_id)
267272
}
268273
}
269-
ty::AssocKind::Const => UrlFragment::AssociatedConstant(name),
270-
ty::AssocKind::Type => UrlFragment::AssociatedType(name),
274+
ty::AssocKind::Const => UrlFragment::Def(FragmentKind::AssociatedConstant, def_id),
275+
ty::AssocKind::Type => UrlFragment::Def(FragmentKind::AssociatedType, def_id),
271276
}
272277
}
273-
}
274278

275-
/// Render the fragment, including the leading `#`.
276-
impl std::fmt::Display for UrlFragment {
277-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278-
write!(f, "#")?;
279-
match self {
280-
UrlFragment::Method(name) => write!(f, "method.{}", name),
281-
UrlFragment::TyMethod(name) => write!(f, "tymethod.{}", name),
282-
UrlFragment::AssociatedConstant(name) => write!(f, "associatedconstant.{}", name),
283-
UrlFragment::AssociatedType(name) => write!(f, "associatedtype.{}", name),
284-
UrlFragment::StructField(name) => write!(f, "structfield.{}", name),
285-
UrlFragment::Variant(name) => write!(f, "variant.{}", name),
286-
UrlFragment::VariantField { variant, field } => {
287-
write!(f, "variant.{}.field.{}", variant, field)
279+
/// Render the fragment, including the leading `#`.
280+
crate fn render(&self, s: &mut String, tcx: TyCtxt<'_>) -> std::fmt::Result {
281+
write!(s, "#")?;
282+
match *self {
283+
UrlFragment::Def(kind, def_id) => {
284+
let name = tcx.item_name(def_id);
285+
match kind {
286+
FragmentKind::Method => write!(s, "method.{}", name),
287+
FragmentKind::TyMethod => write!(s, "tymethod.{}", name),
288+
FragmentKind::AssociatedConstant => write!(s, "associatedconstant.{}", name),
289+
FragmentKind::AssociatedType => write!(s, "associatedtype.{}", name),
290+
FragmentKind::StructField => write!(s, "structfield.{}", name),
291+
FragmentKind::Variant => write!(s, "variant.{}", name),
292+
FragmentKind::VariantField => {
293+
let variant = tcx.item_name(tcx.parent(def_id).unwrap());
294+
write!(s, "variant.{}.field.{}", variant, name)
295+
}
296+
}
288297
}
289-
UrlFragment::UserWritten(raw) => write!(f, "{}", raw),
298+
UrlFragment::UserWritten(ref raw) => write!(s, "{}", raw),
290299
}
291300
}
292301
}
@@ -387,13 +396,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
387396
}
388397
match tcx.type_of(did).kind() {
389398
ty::Adt(def, _) if def.is_enum() => {
390-
if def.all_fields().any(|item| item.ident.name == variant_field_name) {
399+
if let Some(field) =
400+
def.all_fields().find(|f| f.ident.name == variant_field_name)
401+
{
391402
Ok((
392403
ty_res,
393-
Some(UrlFragment::VariantField {
394-
variant: variant_name,
395-
field: variant_field_name,
396-
}),
404+
Some(UrlFragment::Def(FragmentKind::VariantField, field.did)),
397405
))
398406
} else {
399407
Err(ResolutionFailure::NotResolved {
@@ -430,7 +438,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
430438
.find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, impl_)
431439
.map(|item| {
432440
let kind = item.kind;
433-
let fragment = UrlFragment::from_assoc_item(item_name, kind, false);
441+
let fragment = UrlFragment::from_assoc_item(item.def_id, kind, false);
434442
(Res::Primitive(prim_ty), fragment, Some((kind.as_def_kind(), item.def_id)))
435443
})
436444
})
@@ -683,7 +691,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
683691

684692
assoc_item.map(|item| {
685693
let kind = item.kind;
686-
let fragment = UrlFragment::from_assoc_item(item_name, kind, false);
694+
let fragment = UrlFragment::from_assoc_item(item.def_id, kind, false);
687695
// HACK(jynelson): `clean` expects the type, not the associated item
688696
// but the disambiguator logic expects the associated item.
689697
// Store the kind in a side channel so that only the disambiguator logic looks at it.
@@ -737,7 +745,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
737745

738746
if let Some(item) = assoc_item {
739747
let kind = item.kind;
740-
let fragment = UrlFragment::from_assoc_item(item_name, kind, false);
748+
let fragment = UrlFragment::from_assoc_item(item.def_id, kind, false);
741749
// HACK(jynelson): `clean` expects the type, not the associated item
742750
// but the disambiguator logic expects the associated item.
743751
// Store the kind in a side channel so that only the disambiguator logic looks at it.
@@ -774,7 +782,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
774782
.find(|item| item.ident.name == item_name)?;
775783
Some((
776784
root_res,
777-
UrlFragment::StructField(field.ident.name),
785+
UrlFragment::Def(FragmentKind::StructField, field.did),
778786
Some((DefKind::Field, field.did)),
779787
))
780788
}
@@ -783,7 +791,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
783791
.find_by_name_and_namespace(tcx, Ident::with_dummy_span(item_name), ns, did)
784792
.map(|item| {
785793
let fragment = UrlFragment::from_assoc_item(
786-
item_name,
794+
item.def_id,
787795
item.kind,
788796
!item.defaultness.has_value(),
789797
);
@@ -919,8 +927,6 @@ fn is_derive_trait_collision<T>(ns: &PerNS<Result<(Res, T), ResolutionFailure<'_
919927

920928
impl<'a, 'tcx> DocVisitor for LinkCollector<'a, 'tcx> {
921929
fn visit_item(&mut self, item: &Item) {
922-
use rustc_middle::ty::DefIdTree;
923-
924930
let parent_node =
925931
item.def_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
926932
if parent_node.is_some() {
@@ -2280,14 +2286,12 @@ fn handle_variant(
22802286
cx: &DocContext<'_>,
22812287
res: Res,
22822288
) -> Result<(Res, Option<UrlFragment>), ErrorKind<'static>> {
2283-
use rustc_middle::ty::DefIdTree;
2284-
22852289
cx.tcx
22862290
.parent(res.def_id(cx.tcx))
22872291
.map(|parent| {
22882292
let parent_def = Res::Def(DefKind::Enum, parent);
22892293
let variant = cx.tcx.expect_variant_res(res.as_hir_res().unwrap());
2290-
(parent_def, Some(UrlFragment::Variant(variant.ident.name)))
2294+
(parent_def, Some(UrlFragment::Def(FragmentKind::Variant, variant.def_id)))
22912295
})
22922296
.ok_or_else(|| ResolutionFailure::NoParentItem.into())
22932297
}

0 commit comments

Comments
 (0)