Skip to content

Commit 3f21c31

Browse files
committedMay 21, 2022
rustdoc: Some link resolution caching cleanup
1 parent c5449f5 commit 3f21c31

File tree

1 file changed

+16
-35
lines changed

1 file changed

+16
-35
lines changed
 

‎src/librustdoc/passes/collect_intra_doc_links.rs

+16-35
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,6 @@ struct DiagnosticInfo<'a> {
277277
link_range: Range<usize>,
278278
}
279279

280-
#[derive(Clone, Debug, Hash)]
281-
struct CachedLink {
282-
res: (Res, Option<UrlFragment>),
283-
}
284-
285280
struct LinkCollector<'a, 'tcx> {
286281
cx: &'a mut DocContext<'tcx>,
287282
/// A stack of modules used to decide what scope to resolve in.
@@ -291,7 +286,7 @@ struct LinkCollector<'a, 'tcx> {
291286
mod_ids: Vec<DefId>,
292287
/// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link.
293288
/// The link will be `None` if it could not be resolved (i.e. the error was cached).
294-
visited_links: FxHashMap<ResolutionInfo, Option<CachedLink>>,
289+
visited_links: FxHashMap<ResolutionInfo, Option<(Res, Option<UrlFragment>)>>,
295290
}
296291

297292
impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
@@ -1060,6 +1055,9 @@ impl LinkCollector<'_, '_> {
10601055
extra_fragment: extra_fragment.clone(),
10611056
},
10621057
diag_info.clone(), // this struct should really be Copy, but Range is not :(
1058+
// For reference-style links we want to report only one error so unsuccessful
1059+
// resolutions are cached, for other links we want to report an error every
1060+
// time so they are not cached.
10631061
matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
10641062
)?;
10651063

@@ -1256,26 +1254,20 @@ impl LinkCollector<'_, '_> {
12561254
&mut self,
12571255
key: ResolutionInfo,
12581256
diag: DiagnosticInfo<'_>,
1259-
cache_resolution_failure: bool,
1257+
// If errors are cached then they are only reported on first ocurrence
1258+
// which we want in some cases but not in others.
1259+
cache_errors: bool,
12601260
) -> Option<(Res, Option<UrlFragment>)> {
1261-
if let Some(ref cached) = self.visited_links.get(&key) {
1262-
match cached {
1263-
Some(cached) => {
1264-
return Some(cached.res.clone());
1265-
}
1266-
None if cache_resolution_failure => return None,
1267-
None => {
1268-
// Although we hit the cache and found a resolution error, this link isn't
1269-
// supposed to cache those. Run link resolution again to emit the expected
1270-
// resolution error.
1271-
}
1261+
if let Some(res) = self.visited_links.get(&key) {
1262+
if res.is_some() || cache_errors {
1263+
return res.clone();
12721264
}
12731265
}
12741266

12751267
let res = self.resolve_with_disambiguator(&key, diag.clone()).and_then(|(res, def_id)| {
12761268
let fragment = match (&key.extra_fragment, def_id) {
12771269
(Some(_), Some(def_id)) => {
1278-
report_anchor_conflict(self.cx, diag, Res::from_def_id(self.cx.tcx, def_id));
1270+
report_anchor_conflict(self.cx, diag, def_id);
12791271
return None;
12801272
}
12811273
(Some(u_frag), None) => Some(UrlFragment::UserWritten(u_frag.clone())),
@@ -1285,21 +1277,10 @@ impl LinkCollector<'_, '_> {
12851277
Some((res, fragment))
12861278
});
12871279

1288-
// Cache only if resolved successfully - don't silence duplicate errors
1289-
if let Some(res) = res {
1290-
// Store result for the actual namespace
1291-
self.visited_links.insert(key, Some(CachedLink { res: res.clone() }));
1292-
1293-
Some(res)
1294-
} else {
1295-
if cache_resolution_failure {
1296-
// For reference-style links we only want to report one resolution error
1297-
// so let's cache them as well.
1298-
self.visited_links.insert(key, None);
1299-
}
1300-
1301-
None
1280+
if res.is_some() || cache_errors {
1281+
self.visited_links.insert(key, res.clone());
13021282
}
1283+
res
13031284
}
13041285

13051286
/// After parsing the disambiguator, resolve the main part of the link.
@@ -1875,8 +1856,8 @@ fn report_multiple_anchors(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
18751856
anchor_failure(cx, diag_info, &msg, 1)
18761857
}
18771858

1878-
fn report_anchor_conflict(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, res: Res) {
1879-
let (link, kind) = (diag_info.ori_link, res.descr());
1859+
fn report_anchor_conflict(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>, def_id: DefId) {
1860+
let (link, kind) = (diag_info.ori_link, Res::from_def_id(cx.tcx, def_id).descr());
18801861
let msg = format!("`{link}` contains an anchor, but links to {kind}s are already anchored");
18811862
anchor_failure(cx, diag_info, &msg, 0)
18821863
}

0 commit comments

Comments
 (0)
Please sign in to comment.