@@ -277,11 +277,6 @@ struct DiagnosticInfo<'a> {
277
277
link_range : Range < usize > ,
278
278
}
279
279
280
- #[ derive( Clone , Debug , Hash ) ]
281
- struct CachedLink {
282
- res : ( Res , Option < UrlFragment > ) ,
283
- }
284
-
285
280
struct LinkCollector < ' a , ' tcx > {
286
281
cx : & ' a mut DocContext < ' tcx > ,
287
282
/// A stack of modules used to decide what scope to resolve in.
@@ -291,7 +286,7 @@ struct LinkCollector<'a, 'tcx> {
291
286
mod_ids : Vec < DefId > ,
292
287
/// Cache the resolved links so we can avoid resolving (and emitting errors for) the same link.
293
288
/// 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 > ) > > ,
295
290
}
296
291
297
292
impl < ' a , ' tcx > LinkCollector < ' a , ' tcx > {
@@ -1060,6 +1055,9 @@ impl LinkCollector<'_, '_> {
1060
1055
extra_fragment : extra_fragment. clone ( ) ,
1061
1056
} ,
1062
1057
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.
1063
1061
matches ! ( ori_link. kind, LinkType :: Reference | LinkType :: Shortcut ) ,
1064
1062
) ?;
1065
1063
@@ -1256,26 +1254,20 @@ impl LinkCollector<'_, '_> {
1256
1254
& mut self ,
1257
1255
key : ResolutionInfo ,
1258
1256
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 ,
1260
1260
) -> 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 ( ) ;
1272
1264
}
1273
1265
}
1274
1266
1275
1267
let res = self . resolve_with_disambiguator ( & key, diag. clone ( ) ) . and_then ( |( res, def_id) | {
1276
1268
let fragment = match ( & key. extra_fragment , def_id) {
1277
1269
( 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) ;
1279
1271
return None ;
1280
1272
}
1281
1273
( Some ( u_frag) , None ) => Some ( UrlFragment :: UserWritten ( u_frag. clone ( ) ) ) ,
@@ -1285,21 +1277,10 @@ impl LinkCollector<'_, '_> {
1285
1277
Some ( ( res, fragment) )
1286
1278
} ) ;
1287
1279
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 ( ) ) ;
1302
1282
}
1283
+ res
1303
1284
}
1304
1285
1305
1286
/// After parsing the disambiguator, resolve the main part of the link.
@@ -1875,8 +1856,8 @@ fn report_multiple_anchors(cx: &DocContext<'_>, diag_info: DiagnosticInfo<'_>) {
1875
1856
anchor_failure ( cx, diag_info, & msg, 1 )
1876
1857
}
1877
1858
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 ( ) ) ;
1880
1861
let msg = format ! ( "`{link}` contains an anchor, but links to {kind}s are already anchored" ) ;
1881
1862
anchor_failure ( cx, diag_info, & msg, 0 )
1882
1863
}
0 commit comments