@@ -108,15 +108,13 @@ impl Res {
108
108
Res :: Primitive ( _) => return Suggestion :: Prefix ( "prim" ) ,
109
109
Res :: Def ( kind, _) => kind,
110
110
} ;
111
- if kind == DefKind :: Macro ( MacroKind :: Bang ) {
112
- return Suggestion :: Macro ;
113
- } else if kind == DefKind :: Fn || kind == DefKind :: AssocFn {
114
- return Suggestion :: Function ;
115
- } else if kind == DefKind :: Field {
116
- return Suggestion :: RemoveDisambiguator ;
117
- }
118
111
119
112
let prefix = match kind {
113
+ DefKind :: Fn | DefKind :: AssocFn => return Suggestion :: Function ,
114
+ DefKind :: Field => return Suggestion :: RemoveDisambiguator ,
115
+ DefKind :: Macro ( MacroKind :: Bang ) => return Suggestion :: Macro ,
116
+
117
+ DefKind :: Macro ( MacroKind :: Derive ) => "derive" ,
120
118
DefKind :: Struct => "struct" ,
121
119
DefKind :: Enum => "enum" ,
122
120
DefKind :: Trait => "trait" ,
@@ -126,7 +124,6 @@ impl Res {
126
124
"const"
127
125
}
128
126
DefKind :: Static ( _) => "static" ,
129
- DefKind :: Macro ( MacroKind :: Derive ) => "derive" ,
130
127
// Now handle things that don't have a specific disambiguator
131
128
_ => match kind
132
129
. ns ( )
@@ -283,20 +280,15 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
283
280
284
281
debug ! ( "looking for enum variant {path_str}" ) ;
285
282
let mut split = path_str. rsplitn ( 3 , "::" ) ;
286
- let variant_field_name = split
287
- . next ( )
288
- . map ( |f| Symbol :: intern ( f) )
289
- . expect ( "fold_item should ensure link is non-empty" ) ;
290
- let variant_name =
291
- // we're not sure this is a variant at all, so use the full string
292
- // If there's no second component, the link looks like `[path]`.
293
- // So there's no partial res and we should say the whole link failed to resolve.
294
- split. next ( ) . map ( |f| Symbol :: intern ( f) ) . ok_or_else ( no_res) ?;
295
- let path = split
296
- . next ( )
297
- // If there's no third component, we saw `[a::b]` before and it failed to resolve.
298
- // So there's no partial res.
299
- . ok_or_else ( no_res) ?;
283
+ let variant_field_name = Symbol :: intern ( split. next ( ) . unwrap ( ) ) ;
284
+ // We're not sure this is a variant at all, so use the full string.
285
+ // If there's no second component, the link looks like `[path]`.
286
+ // So there's no partial res and we should say the whole link failed to resolve.
287
+ let variant_name = Symbol :: intern ( split. next ( ) . ok_or_else ( no_res) ?) ;
288
+
289
+ // If there's no third component, we saw `[a::b]` before and it failed to resolve.
290
+ // So there's no partial res.
291
+ let path = split. next ( ) . ok_or_else ( no_res) ?;
300
292
let ty_res = self . resolve_path ( & path, TypeNS , item_id, module_id) . ok_or_else ( no_res) ?;
301
293
302
294
match ty_res {
@@ -447,41 +439,29 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
447
439
}
448
440
449
441
// Try looking for methods and associated items.
450
- let mut split = path_str. rsplitn ( 2 , "::" ) ;
451
- // NB: `split`'s first element is always defined, even if the delimiter was not present.
452
- // NB: `item_str` could be empty when resolving in the root namespace (e.g. `::std`).
453
- let item_str = split. next ( ) . unwrap ( ) ;
454
- let item_name = Symbol :: intern ( item_str) ;
455
- let path_root = split
456
- . next ( )
442
+ // NB: `path_root` could be empty when resolving in the root namespace (e.g. `::std`).
443
+ let ( path_root, item_str) = path_str. rsplit_once ( "::" ) . ok_or_else ( || {
457
444
// If there's no `::`, it's not an associated item.
458
445
// So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved.
459
- . ok_or_else ( || {
460
- debug ! ( "found no `::`, assuming {item_name} was correctly not in scope" ) ;
461
- UnresolvedPath {
462
- item_id,
463
- module_id,
464
- partial_res : None ,
465
- unresolved : item_str. into ( ) ,
466
- }
467
- } ) ?;
446
+ debug ! ( "found no `::`, assuming {path_str} was correctly not in scope" ) ;
447
+ UnresolvedPath { item_id, module_id, partial_res : None , unresolved : path_str. into ( ) }
448
+ } ) ?;
449
+ let item_name = Symbol :: intern ( item_str) ;
468
450
469
451
// FIXME(#83862): this arbitrarily gives precedence to primitives over modules to support
470
452
// links to primitives when `#[rustc_doc_primitive]` is present. It should give an ambiguity
471
453
// error instead and special case *only* modules with `#[rustc_doc_primitive]`, not all
472
454
// primitives.
473
- match resolve_primitive ( & path_root, TypeNS )
474
- . or_else ( || self . resolve_path ( & path_root, TypeNS , item_id, module_id) )
475
- . and_then ( |ty_res| {
476
- let candidates = self
477
- . resolve_associated_item ( ty_res, item_name, ns, module_id)
455
+ match resolve_primitive ( path_root, TypeNS )
456
+ . or_else ( || self . resolve_path ( path_root, TypeNS , item_id, module_id) )
457
+ . map ( |ty_res| {
458
+ self . resolve_associated_item ( ty_res, item_name, ns, module_id)
478
459
. into_iter ( )
479
460
. map ( |( res, def_id) | ( res, Some ( def_id) ) )
480
- . collect :: < Vec < _ > > ( ) ;
481
- if !candidates. is_empty ( ) { Some ( candidates) } else { None }
461
+ . collect :: < Vec < _ > > ( )
482
462
} ) {
483
- Some ( r) => Ok ( r) ,
484
- None => {
463
+ Some ( r) if !r . is_empty ( ) => Ok ( r) ,
464
+ _ => {
485
465
if ns == Namespace :: ValueNS {
486
466
self . variant_field ( path_str, item_id, module_id)
487
467
. map ( |( res, def_id) | vec ! [ ( res, Some ( def_id) ) ] )
@@ -1262,16 +1242,18 @@ impl LinkCollector<'_, '_> {
1262
1242
self . report_rawptr_assoc_feature_gate ( diag. dox , & diag. link_range , diag. item ) ;
1263
1243
return None ;
1264
1244
} else {
1265
- candidates = vec ! [ candidates [ 0 ] ] ;
1245
+ candidates = vec ! [ * candidate ] ;
1266
1246
}
1267
1247
}
1268
1248
1269
1249
// If there are multiple items with the same "kind" (for example, both "associated types")
1270
1250
// and after removing duplicated kinds, only one remains, the `ambiguity_error` function
1271
1251
// won't emit an error. So at this point, we can just take the first candidate as it was
1272
1252
// the first retrieved and use it to generate the link.
1273
- if candidates. len ( ) > 1 && !ambiguity_error ( self . cx , & diag, & key. path_str , & candidates) {
1274
- candidates = vec ! [ candidates[ 0 ] ] ;
1253
+ if let [ candidate, _candidate2, ..] = * candidates
1254
+ && !ambiguity_error ( self . cx , & diag, & key. path_str , & candidates)
1255
+ {
1256
+ candidates = vec ! [ candidate] ;
1275
1257
}
1276
1258
1277
1259
if let & [ ( res, def_id) ] = candidates. as_slice ( ) {
@@ -1321,12 +1303,11 @@ impl LinkCollector<'_, '_> {
1321
1303
let mut err = ResolutionFailure :: NotResolved ( err) ;
1322
1304
for other_ns in [ TypeNS , ValueNS , MacroNS ] {
1323
1305
if other_ns != expected_ns {
1324
- if let Ok ( res) =
1325
- self . resolve ( path_str, other_ns, item_id, module_id)
1326
- && !res. is_empty ( )
1306
+ if let Ok ( & [ res, ..] ) =
1307
+ self . resolve ( path_str, other_ns, item_id, module_id) . as_deref ( )
1327
1308
{
1328
1309
err = ResolutionFailure :: WrongNamespace {
1329
- res : full_res ( self . cx . tcx , res[ 0 ] ) ,
1310
+ res : full_res ( self . cx . tcx , res) ,
1330
1311
expected_ns,
1331
1312
} ;
1332
1313
break ;
@@ -1747,7 +1728,6 @@ fn report_diagnostic(
1747
1728
lint. note ( format ! (
1748
1729
"the link appears in this line:\n \n {line}\n \
1749
1730
{indicator: <before$}{indicator:^<found$}",
1750
- line = line,
1751
1731
indicator = "" ,
1752
1732
before = md_range. start - last_new_line_offset,
1753
1733
found = md_range. len( ) ,
@@ -1808,18 +1788,13 @@ fn resolution_failure(
1808
1788
1809
1789
let item_id = * item_id;
1810
1790
let module_id = * module_id;
1811
- // FIXME(jynelson): this might conflict with my `Self` fix in #76467
1812
- // FIXME: maybe use itertools `collect_tuple` instead?
1813
- fn split ( path : & str ) -> Option < ( & str , & str ) > {
1814
- let mut splitter = path. rsplitn ( 2 , "::" ) ;
1815
- splitter. next ( ) . and_then ( |right| splitter. next ( ) . map ( |left| ( left, right) ) )
1816
- }
1817
1791
1818
1792
// Check if _any_ parent of the path gets resolved.
1819
1793
// If so, report it and say the first which failed; if not, say the first path segment didn't resolve.
1820
1794
let mut name = path_str;
1821
1795
' outer: loop {
1822
- let Some ( ( start, end) ) = split ( name) else {
1796
+ // FIXME(jynelson): this might conflict with my `Self` fix in #76467
1797
+ let Some ( ( start, end) ) = name. rsplit_once ( "::" ) else {
1823
1798
// avoid bug that marked [Quux::Z] as missing Z, not Quux
1824
1799
if partial_res. is_none ( ) {
1825
1800
* unresolved = name. into ( ) ;
@@ -1830,8 +1805,8 @@ fn resolution_failure(
1830
1805
for ns in [ TypeNS , ValueNS , MacroNS ] {
1831
1806
if let Ok ( v_res) = collector. resolve ( start, ns, item_id, module_id) {
1832
1807
debug ! ( "found partial_res={v_res:?}" ) ;
1833
- if ! v_res. is_empty ( ) {
1834
- * partial_res = Some ( full_res ( tcx, v_res [ 0 ] ) ) ;
1808
+ if let Some ( & res ) = v_res. first ( ) {
1809
+ * partial_res = Some ( full_res ( tcx, res ) ) ;
1835
1810
* unresolved = end. into ( ) ;
1836
1811
break ' outer;
1837
1812
}
0 commit comments