@@ -110,7 +110,6 @@ impl Res {
110
110
111
111
let prefix = match kind {
112
112
DefKind :: Fn | DefKind :: AssocFn => return Suggestion :: Function ,
113
- DefKind :: Field => return Suggestion :: RemoveDisambiguator ,
114
113
DefKind :: Macro ( MacroKind :: Bang ) => return Suggestion :: Macro ,
115
114
116
115
DefKind :: Macro ( MacroKind :: Derive ) => "derive" ,
@@ -123,6 +122,8 @@ impl Res {
123
122
"const"
124
123
}
125
124
DefKind :: Static { .. } => "static" ,
125
+ DefKind :: Field => "field" ,
126
+ DefKind :: Variant | DefKind :: Ctor ( ..) => "variant" ,
126
127
// Now handle things that don't have a specific disambiguator
127
128
_ => match kind
128
129
. ns ( )
@@ -415,6 +416,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
415
416
& mut self ,
416
417
path_str : & ' path str ,
417
418
ns : Namespace ,
419
+ disambiguator : Option < Disambiguator > ,
418
420
item_id : DefId ,
419
421
module_id : DefId ,
420
422
) -> Result < Vec < ( Res , Option < DefId > ) > , UnresolvedPath < ' path > > {
@@ -454,7 +456,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
454
456
match resolve_primitive ( path_root, TypeNS )
455
457
. or_else ( || self . resolve_path ( path_root, TypeNS , item_id, module_id) )
456
458
. map ( |ty_res| {
457
- self . resolve_associated_item ( ty_res, item_name, ns, module_id)
459
+ self . resolve_associated_item ( ty_res, item_name, ns, disambiguator , module_id)
458
460
. into_iter ( )
459
461
. map ( |( res, def_id) | ( res, Some ( def_id) ) )
460
462
. collect :: < Vec < _ > > ( )
@@ -557,6 +559,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
557
559
root_res : Res ,
558
560
item_name : Symbol ,
559
561
ns : Namespace ,
562
+ disambiguator : Option < Disambiguator > ,
560
563
module_id : DefId ,
561
564
) -> Vec < ( Res , DefId ) > {
562
565
let tcx = self . cx . tcx ;
@@ -583,7 +586,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
583
586
// FIXME: if the associated item is defined directly on the type alias,
584
587
// it will show up on its documentation page, we should link there instead.
585
588
let Some ( res) = self . def_id_to_res ( did) else { return Vec :: new ( ) } ;
586
- self . resolve_associated_item ( res, item_name, ns, module_id)
589
+ self . resolve_associated_item ( res, item_name, ns, disambiguator , module_id)
587
590
}
588
591
Res :: Def (
589
592
def_kind @ ( DefKind :: Struct | DefKind :: Union | DefKind :: Enum | DefKind :: ForeignTy ) ,
@@ -604,6 +607,39 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
604
607
}
605
608
}
606
609
610
+ let search_for_field = || {
611
+ let ( DefKind :: Struct | DefKind :: Union ) = def_kind else { return vec ! [ ] } ;
612
+ debug ! ( "looking for fields named {item_name} for {did:?}" ) ;
613
+ // FIXME: this doesn't really belong in `associated_item` (maybe `variant_field` is better?)
614
+ // NOTE: it's different from variant_field because it only resolves struct fields,
615
+ // not variant fields (2 path segments, not 3).
616
+ //
617
+ // We need to handle struct (and union) fields in this code because
618
+ // syntactically their paths are identical to associated item paths:
619
+ // `module::Type::field` and `module::Type::Assoc`.
620
+ //
621
+ // On the other hand, variant fields can't be mistaken for associated
622
+ // items because they look like this: `module::Type::Variant::field`.
623
+ //
624
+ // Variants themselves don't need to be handled here, even though
625
+ // they also look like associated items (`module::Type::Variant`),
626
+ // because they are real Rust syntax (unlike the intra-doc links
627
+ // field syntax) and are handled by the compiler's resolver.
628
+ let ty:: Adt ( def, _) = tcx. type_of ( did) . instantiate_identity ( ) . kind ( ) else {
629
+ unreachable ! ( )
630
+ } ;
631
+ def. non_enum_variant ( )
632
+ . fields
633
+ . iter ( )
634
+ . filter ( |field| field. name == item_name)
635
+ . map ( |field| ( root_res, field. did ) )
636
+ . collect :: < Vec < _ > > ( )
637
+ } ;
638
+
639
+ if let Some ( Disambiguator :: Kind ( DefKind :: Field ) ) = disambiguator {
640
+ return search_for_field ( ) ;
641
+ }
642
+
607
643
// Checks if item_name belongs to `impl SomeItem`
608
644
let mut assoc_items: Vec < _ > = tcx
609
645
. inherent_impls ( did)
@@ -646,32 +682,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
646
682
if ns != Namespace :: ValueNS {
647
683
return Vec :: new ( ) ;
648
684
}
649
- debug ! ( "looking for fields named {item_name} for {did:?}" ) ;
650
- // FIXME: this doesn't really belong in `associated_item` (maybe `variant_field` is better?)
651
- // NOTE: it's different from variant_field because it only resolves struct fields,
652
- // not variant fields (2 path segments, not 3).
653
- //
654
- // We need to handle struct (and union) fields in this code because
655
- // syntactically their paths are identical to associated item paths:
656
- // `module::Type::field` and `module::Type::Assoc`.
657
- //
658
- // On the other hand, variant fields can't be mistaken for associated
659
- // items because they look like this: `module::Type::Variant::field`.
660
- //
661
- // Variants themselves don't need to be handled here, even though
662
- // they also look like associated items (`module::Type::Variant`),
663
- // because they are real Rust syntax (unlike the intra-doc links
664
- // field syntax) and are handled by the compiler's resolver.
665
- let def = match tcx. type_of ( did) . instantiate_identity ( ) . kind ( ) {
666
- ty:: Adt ( def, _) if !def. is_enum ( ) => def,
667
- _ => return Vec :: new ( ) ,
668
- } ;
669
- def. non_enum_variant ( )
670
- . fields
671
- . iter ( )
672
- . filter ( |field| field. name == item_name)
673
- . map ( |field| ( root_res, field. did ) )
674
- . collect :: < Vec < _ > > ( )
685
+
686
+ search_for_field ( )
675
687
}
676
688
Res :: Def ( DefKind :: Trait , did) => filter_assoc_items_by_name_and_namespace (
677
689
tcx,
@@ -1297,7 +1309,7 @@ impl LinkCollector<'_, '_> {
1297
1309
1298
1310
match disambiguator. map ( Disambiguator :: ns) {
1299
1311
Some ( expected_ns) => {
1300
- match self . resolve ( path_str, expected_ns, item_id, module_id) {
1312
+ match self . resolve ( path_str, expected_ns, disambiguator , item_id, module_id) {
1301
1313
Ok ( candidates) => candidates,
1302
1314
Err ( err) => {
1303
1315
// We only looked in one namespace. Try to give a better error if possible.
@@ -1306,8 +1318,9 @@ impl LinkCollector<'_, '_> {
1306
1318
let mut err = ResolutionFailure :: NotResolved ( err) ;
1307
1319
for other_ns in [ TypeNS , ValueNS , MacroNS ] {
1308
1320
if other_ns != expected_ns {
1309
- if let Ok ( & [ res, ..] ) =
1310
- self . resolve ( path_str, other_ns, item_id, module_id) . as_deref ( )
1321
+ if let Ok ( & [ res, ..] ) = self
1322
+ . resolve ( path_str, other_ns, None , item_id, module_id)
1323
+ . as_deref ( )
1311
1324
{
1312
1325
err = ResolutionFailure :: WrongNamespace {
1313
1326
res : full_res ( self . cx . tcx , res) ,
@@ -1327,7 +1340,7 @@ impl LinkCollector<'_, '_> {
1327
1340
None => {
1328
1341
// Try everything!
1329
1342
let mut candidate = |ns| {
1330
- self . resolve ( path_str, ns, item_id, module_id)
1343
+ self . resolve ( path_str, ns, None , item_id, module_id)
1331
1344
. map_err ( ResolutionFailure :: NotResolved )
1332
1345
} ;
1333
1346
@@ -1531,6 +1544,8 @@ impl Disambiguator {
1531
1544
} ) ,
1532
1545
"function" | "fn" | "method" => Kind ( DefKind :: Fn ) ,
1533
1546
"derive" => Kind ( DefKind :: Macro ( MacroKind :: Derive ) ) ,
1547
+ "field" => Kind ( DefKind :: Field ) ,
1548
+ "variant" => Kind ( DefKind :: Variant ) ,
1534
1549
"type" => NS ( Namespace :: TypeNS ) ,
1535
1550
"value" => NS ( Namespace :: ValueNS ) ,
1536
1551
"macro" => NS ( Namespace :: MacroNS ) ,
@@ -1569,6 +1584,8 @@ impl Disambiguator {
1569
1584
fn ns ( self ) -> Namespace {
1570
1585
match self {
1571
1586
Self :: Namespace ( n) => n,
1587
+ // for purposes of link resolution, fields are in the value namespace.
1588
+ Self :: Kind ( DefKind :: Field ) => ValueNS ,
1572
1589
Self :: Kind ( k) => {
1573
1590
k. ns ( ) . expect ( "only DefKinds with a valid namespace can be disambiguators" )
1574
1591
}
@@ -1603,8 +1620,6 @@ enum Suggestion {
1603
1620
Function ,
1604
1621
/// `m!`
1605
1622
Macro ,
1606
- /// `foo` without any disambiguator
1607
- RemoveDisambiguator ,
1608
1623
}
1609
1624
1610
1625
impl Suggestion {
@@ -1613,7 +1628,6 @@ impl Suggestion {
1613
1628
Self :: Prefix ( x) => format ! ( "prefix with `{x}@`" ) . into ( ) ,
1614
1629
Self :: Function => "add parentheses" . into ( ) ,
1615
1630
Self :: Macro => "add an exclamation mark" . into ( ) ,
1616
- Self :: RemoveDisambiguator => "remove the disambiguator" . into ( ) ,
1617
1631
}
1618
1632
}
1619
1633
@@ -1623,13 +1637,11 @@ impl Suggestion {
1623
1637
Self :: Prefix ( prefix) => format ! ( "{prefix}@{path_str}" ) ,
1624
1638
Self :: Function => format ! ( "{path_str}()" ) ,
1625
1639
Self :: Macro => format ! ( "{path_str}!" ) ,
1626
- Self :: RemoveDisambiguator => path_str. into ( ) ,
1627
1640
}
1628
1641
}
1629
1642
1630
1643
fn as_help_span (
1631
1644
& self ,
1632
- path_str : & str ,
1633
1645
ori_link : & str ,
1634
1646
sp : rustc_span:: Span ,
1635
1647
) -> Vec < ( rustc_span:: Span , String ) > {
@@ -1677,7 +1689,6 @@ impl Suggestion {
1677
1689
}
1678
1690
sugg
1679
1691
}
1680
- Self :: RemoveDisambiguator => vec ! [ ( sp, path_str. into( ) ) ] ,
1681
1692
}
1682
1693
}
1683
1694
}
@@ -1826,7 +1837,9 @@ fn resolution_failure(
1826
1837
} ;
1827
1838
name = start;
1828
1839
for ns in [ TypeNS , ValueNS , MacroNS ] {
1829
- if let Ok ( v_res) = collector. resolve ( start, ns, item_id, module_id) {
1840
+ if let Ok ( v_res) =
1841
+ collector. resolve ( start, ns, None , item_id, module_id)
1842
+ {
1830
1843
debug ! ( "found partial_res={v_res:?}" ) ;
1831
1844
if let Some ( & res) = v_res. first ( ) {
1832
1845
* partial_res = Some ( full_res ( tcx, res) ) ;
@@ -2164,7 +2177,7 @@ fn suggest_disambiguator(
2164
2177
} ;
2165
2178
2166
2179
if let ( Some ( sp) , Some ( ori_link) ) = ( sp, ori_link) {
2167
- let mut spans = suggestion. as_help_span ( path_str , ori_link, sp) ;
2180
+ let mut spans = suggestion. as_help_span ( ori_link, sp) ;
2168
2181
if spans. len ( ) > 1 {
2169
2182
diag. multipart_suggestion ( help, spans, Applicability :: MaybeIncorrect ) ;
2170
2183
} else {
0 commit comments