@@ -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-
285280struct 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
297292impl < ' 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