@@ -106,15 +106,13 @@ impl Res {
106106 Res :: Primitive ( _) => return Suggestion :: Prefix ( "prim" ) ,
107107 Res :: Def ( kind, _) => kind,
108108 } ;
109- if kind == DefKind :: Macro ( MacroKind :: Bang ) {
110- return Suggestion :: Macro ;
111- } else if kind == DefKind :: Fn || kind == DefKind :: AssocFn {
112- return Suggestion :: Function ;
113- } else if kind == DefKind :: Field {
114- return Suggestion :: RemoveDisambiguator ;
115- }
116109
117110 let prefix = match kind {
111+ DefKind :: Fn | DefKind :: AssocFn => return Suggestion :: Function ,
112+ DefKind :: Field => return Suggestion :: RemoveDisambiguator ,
113+ DefKind :: Macro ( MacroKind :: Bang ) => return Suggestion :: Macro ,
114+
115+ DefKind :: Macro ( MacroKind :: Derive ) => "derive" ,
118116 DefKind :: Struct => "struct" ,
119117 DefKind :: Enum => "enum" ,
120118 DefKind :: Trait => "trait" ,
@@ -124,7 +122,6 @@ impl Res {
124122 "const"
125123 }
126124 DefKind :: Static ( _) => "static" ,
127- DefKind :: Macro ( MacroKind :: Derive ) => "derive" ,
128125 // Now handle things that don't have a specific disambiguator
129126 _ => match kind
130127 . ns ( )
@@ -281,20 +278,15 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
281278
282279 debug ! ( "looking for enum variant {path_str}" ) ;
283280 let mut split = path_str. rsplitn ( 3 , "::" ) ;
284- let variant_field_name = split
285- . next ( )
286- . map ( |f| Symbol :: intern ( f) )
287- . expect ( "fold_item should ensure link is non-empty" ) ;
288- let variant_name =
289- // we're not sure this is a variant at all, so use the full string
290- // If there's no second component, the link looks like `[path]`.
291- // So there's no partial res and we should say the whole link failed to resolve.
292- split. next ( ) . map ( |f| Symbol :: intern ( f) ) . ok_or_else ( no_res) ?;
293- let path = split
294- . next ( )
295- // If there's no third component, we saw `[a::b]` before and it failed to resolve.
296- // So there's no partial res.
297- . ok_or_else ( no_res) ?;
281+ let variant_field_name = Symbol :: intern ( split. next ( ) . unwrap ( ) ) ;
282+ // We're not sure this is a variant at all, so use the full string.
283+ // If there's no second component, the link looks like `[path]`.
284+ // So there's no partial res and we should say the whole link failed to resolve.
285+ let variant_name = Symbol :: intern ( split. next ( ) . ok_or_else ( no_res) ?) ;
286+
287+ // If there's no third component, we saw `[a::b]` before and it failed to resolve.
288+ // So there's no partial res.
289+ let path = split. next ( ) . ok_or_else ( no_res) ?;
298290 let ty_res = self . resolve_path ( & path, TypeNS , item_id, module_id) . ok_or_else ( no_res) ?;
299291
300292 match ty_res {
@@ -443,41 +435,29 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
443435 }
444436
445437 // Try looking for methods and associated items.
446- let mut split = path_str. rsplitn ( 2 , "::" ) ;
447- // NB: `split`'s first element is always defined, even if the delimiter was not present.
448- // NB: `item_str` could be empty when resolving in the root namespace (e.g. `::std`).
449- let item_str = split. next ( ) . unwrap ( ) ;
450- let item_name = Symbol :: intern ( item_str) ;
451- let path_root = split
452- . next ( )
438+ // NB: `path_root` could be empty when resolving in the root namespace (e.g. `::std`).
439+ let ( path_root, item_str) = path_str. rsplit_once ( "::" ) . ok_or_else ( || {
453440 // If there's no `::`, it's not an associated item.
454441 // So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved.
455- . ok_or_else ( || {
456- debug ! ( "found no `::`, assuming {item_name} was correctly not in scope" ) ;
457- UnresolvedPath {
458- item_id,
459- module_id,
460- partial_res : None ,
461- unresolved : item_str. into ( ) ,
462- }
463- } ) ?;
442+ debug ! ( "found no `::`, assuming {path_str} was correctly not in scope" ) ;
443+ UnresolvedPath { item_id, module_id, partial_res : None , unresolved : path_str. into ( ) }
444+ } ) ?;
445+ let item_name = Symbol :: intern ( item_str) ;
464446
465447 // FIXME(#83862): this arbitrarily gives precedence to primitives over modules to support
466448 // links to primitives when `#[rustc_doc_primitive]` is present. It should give an ambiguity
467449 // error instead and special case *only* modules with `#[rustc_doc_primitive]`, not all
468450 // primitives.
469- match resolve_primitive ( & path_root, TypeNS )
470- . or_else ( || self . resolve_path ( & path_root, TypeNS , item_id, module_id) )
471- . and_then ( |ty_res| {
472- let candidates = self
473- . resolve_associated_item ( ty_res, item_name, ns, module_id)
451+ match resolve_primitive ( path_root, TypeNS )
452+ . or_else ( || self . resolve_path ( path_root, TypeNS , item_id, module_id) )
453+ . map ( |ty_res| {
454+ self . resolve_associated_item ( ty_res, item_name, ns, module_id)
474455 . into_iter ( )
475456 . map ( |( res, def_id) | ( res, Some ( def_id) ) )
476- . collect :: < Vec < _ > > ( ) ;
477- if !candidates. is_empty ( ) { Some ( candidates) } else { None }
457+ . collect :: < Vec < _ > > ( )
478458 } ) {
479- Some ( r) => Ok ( r) ,
480- None => {
459+ Some ( r) if !r . is_empty ( ) => Ok ( r) ,
460+ _ => {
481461 if ns == Namespace :: ValueNS {
482462 self . variant_field ( path_str, item_id, module_id)
483463 . map ( |( res, def_id) | vec ! [ ( res, Some ( def_id) ) ] )
@@ -1257,16 +1237,18 @@ impl LinkCollector<'_, '_> {
12571237 self . report_rawptr_assoc_feature_gate ( diag. dox , & diag. link_range , diag. item ) ;
12581238 return None ;
12591239 } else {
1260- candidates = vec ! [ candidates [ 0 ] ] ;
1240+ candidates = vec ! [ * candidate ] ;
12611241 }
12621242 }
12631243
12641244 // If there are multiple items with the same "kind" (for example, both "associated types")
12651245 // and after removing duplicated kinds, only one remains, the `ambiguity_error` function
12661246 // won't emit an error. So at this point, we can just take the first candidate as it was
12671247 // the first retrieved and use it to generate the link.
1268- if candidates. len ( ) > 1 && !ambiguity_error ( self . cx , & diag, & key. path_str , & candidates) {
1269- candidates = vec ! [ candidates[ 0 ] ] ;
1248+ if let [ candidate, _candidate2, ..] = * candidates
1249+ && !ambiguity_error ( self . cx , & diag, & key. path_str , & candidates)
1250+ {
1251+ candidates = vec ! [ candidate] ;
12701252 }
12711253
12721254 if let & [ ( res, def_id) ] = candidates. as_slice ( ) {
@@ -1316,12 +1298,11 @@ impl LinkCollector<'_, '_> {
13161298 let mut err = ResolutionFailure :: NotResolved ( err) ;
13171299 for other_ns in [ TypeNS , ValueNS , MacroNS ] {
13181300 if other_ns != expected_ns {
1319- if let Ok ( res) =
1320- self . resolve ( path_str, other_ns, item_id, module_id) &&
1321- !res. is_empty ( )
1301+ if let Ok ( & [ res, ..] ) =
1302+ self . resolve ( path_str, other_ns, item_id, module_id) . as_deref ( )
13221303 {
13231304 err = ResolutionFailure :: WrongNamespace {
1324- res : full_res ( self . cx . tcx , res[ 0 ] ) ,
1305+ res : full_res ( self . cx . tcx , res) ,
13251306 expected_ns,
13261307 } ;
13271308 break ;
@@ -1746,7 +1727,6 @@ fn report_diagnostic(
17461727 lint. note ( format ! (
17471728 "the link appears in this line:\n \n {line}\n \
17481729 {indicator: <before$}{indicator:^<found$}",
1749- line = line,
17501730 indicator = "" ,
17511731 before = md_range. start - last_new_line_offset,
17521732 found = md_range. len( ) ,
@@ -1807,18 +1787,13 @@ fn resolution_failure(
18071787
18081788 let item_id = * item_id;
18091789 let module_id = * module_id;
1810- // FIXME(jynelson): this might conflict with my `Self` fix in #76467
1811- // FIXME: maybe use itertools `collect_tuple` instead?
1812- fn split ( path : & str ) -> Option < ( & str , & str ) > {
1813- let mut splitter = path. rsplitn ( 2 , "::" ) ;
1814- splitter. next ( ) . and_then ( |right| splitter. next ( ) . map ( |left| ( left, right) ) )
1815- }
18161790
18171791 // Check if _any_ parent of the path gets resolved.
18181792 // If so, report it and say the first which failed; if not, say the first path segment didn't resolve.
18191793 let mut name = path_str;
18201794 ' outer: loop {
1821- let Some ( ( start, end) ) = split ( name) else {
1795+ // FIXME(jynelson): this might conflict with my `Self` fix in #76467
1796+ let Some ( ( start, end) ) = name. rsplit_once ( "::" ) else {
18221797 // avoid bug that marked [Quux::Z] as missing Z, not Quux
18231798 if partial_res. is_none ( ) {
18241799 * unresolved = name. into ( ) ;
@@ -1829,8 +1804,8 @@ fn resolution_failure(
18291804 for ns in [ TypeNS , ValueNS , MacroNS ] {
18301805 if let Ok ( v_res) = collector. resolve ( start, ns, item_id, module_id) {
18311806 debug ! ( "found partial_res={v_res:?}" ) ;
1832- if ! v_res. is_empty ( ) {
1833- * partial_res = Some ( full_res ( tcx, v_res [ 0 ] ) ) ;
1807+ if let Some ( & res ) = v_res. first ( ) {
1808+ * partial_res = Some ( full_res ( tcx, res ) ) ;
18341809 * unresolved = end. into ( ) ;
18351810 break ' outer;
18361811 }
0 commit comments