@@ -13,7 +13,7 @@ use rustc_hir::def::{
1313 PerNS ,
1414} ;
1515use rustc_hir:: def_id:: { CrateNum , DefId } ;
16- use rustc_middle:: ty:: { Ty , TyCtxt } ;
16+ use rustc_middle:: ty:: { DefIdTree , Ty , TyCtxt } ;
1717use rustc_middle:: { bug, span_bug, ty} ;
1818use rustc_resolve:: ParentScope ;
1919use rustc_session:: lint:: Lint ;
@@ -27,6 +27,7 @@ use pulldown_cmark::LinkType;
2727use std:: borrow:: Cow ;
2828use std:: cell:: Cell ;
2929use std:: convert:: { TryFrom , TryInto } ;
30+ use std:: fmt:: Write ;
3031use std:: mem;
3132use std:: ops:: Range ;
3233
@@ -240,53 +241,61 @@ enum AnchorFailure {
240241
241242#[ derive( Clone , Debug , Hash , PartialEq , Eq ) ]
242243crate enum UrlFragment {
243- Method ( Symbol ) ,
244- TyMethod ( Symbol ) ,
245- AssociatedConstant ( Symbol ) ,
246- AssociatedType ( Symbol ) ,
244+ Def ( FragmentKind , DefId ) ,
245+ UserWritten ( String ) ,
246+ }
247247
248- StructField ( Symbol ) ,
249- Variant ( Symbol ) ,
250- VariantField { variant : Symbol , field : Symbol } ,
248+ #[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq ) ]
249+ crate enum FragmentKind {
250+ Method ,
251+ TyMethod ,
252+ AssociatedConstant ,
253+ AssociatedType ,
251254
252- UserWritten ( String ) ,
255+ StructField ,
256+ Variant ,
257+ VariantField ,
253258}
254259
255260impl UrlFragment {
256261 /// Create a fragment for an associated item.
257262 ///
258263 /// `is_prototype` is whether this associated item is a trait method
259264 /// without a default definition.
260- fn from_assoc_item ( name : Symbol , kind : ty:: AssocKind , is_prototype : bool ) -> Self {
265+ fn from_assoc_item ( def_id : DefId , kind : ty:: AssocKind , is_prototype : bool ) -> Self {
261266 match kind {
262267 ty:: AssocKind :: Fn => {
263268 if is_prototype {
264- UrlFragment :: TyMethod ( name )
269+ UrlFragment :: Def ( FragmentKind :: TyMethod , def_id )
265270 } else {
266- UrlFragment :: Method ( name )
271+ UrlFragment :: Def ( FragmentKind :: Method , def_id )
267272 }
268273 }
269- ty:: AssocKind :: Const => UrlFragment :: AssociatedConstant ( name ) ,
270- ty:: AssocKind :: Type => UrlFragment :: AssociatedType ( name ) ,
274+ ty:: AssocKind :: Const => UrlFragment :: Def ( FragmentKind :: AssociatedConstant , def_id ) ,
275+ ty:: AssocKind :: Type => UrlFragment :: Def ( FragmentKind :: AssociatedType , def_id ) ,
271276 }
272277 }
273- }
274278
275- /// Render the fragment, including the leading `#`.
276- impl std:: fmt:: Display for UrlFragment {
277- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
278- write ! ( f, "#" ) ?;
279- match self {
280- UrlFragment :: Method ( name) => write ! ( f, "method.{}" , name) ,
281- UrlFragment :: TyMethod ( name) => write ! ( f, "tymethod.{}" , name) ,
282- UrlFragment :: AssociatedConstant ( name) => write ! ( f, "associatedconstant.{}" , name) ,
283- UrlFragment :: AssociatedType ( name) => write ! ( f, "associatedtype.{}" , name) ,
284- UrlFragment :: StructField ( name) => write ! ( f, "structfield.{}" , name) ,
285- UrlFragment :: Variant ( name) => write ! ( f, "variant.{}" , name) ,
286- UrlFragment :: VariantField { variant, field } => {
287- write ! ( f, "variant.{}.field.{}" , variant, field)
279+ /// Render the fragment, including the leading `#`.
280+ crate fn render ( & self , s : & mut String , tcx : TyCtxt < ' _ > ) -> std:: fmt:: Result {
281+ write ! ( s, "#" ) ?;
282+ match * self {
283+ UrlFragment :: Def ( kind, def_id) => {
284+ let name = tcx. item_name ( def_id) ;
285+ match kind {
286+ FragmentKind :: Method => write ! ( s, "method.{}" , name) ,
287+ FragmentKind :: TyMethod => write ! ( s, "tymethod.{}" , name) ,
288+ FragmentKind :: AssociatedConstant => write ! ( s, "associatedconstant.{}" , name) ,
289+ FragmentKind :: AssociatedType => write ! ( s, "associatedtype.{}" , name) ,
290+ FragmentKind :: StructField => write ! ( s, "structfield.{}" , name) ,
291+ FragmentKind :: Variant => write ! ( s, "variant.{}" , name) ,
292+ FragmentKind :: VariantField => {
293+ let variant = tcx. item_name ( tcx. parent ( def_id) . unwrap ( ) ) ;
294+ write ! ( s, "variant.{}.field.{}" , variant, name)
295+ }
296+ }
288297 }
289- UrlFragment :: UserWritten ( raw) => write ! ( f , "{}" , raw) ,
298+ UrlFragment :: UserWritten ( ref raw) => write ! ( s , "{}" , raw) ,
290299 }
291300 }
292301}
@@ -387,13 +396,12 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
387396 }
388397 match tcx. type_of ( did) . kind ( ) {
389398 ty:: Adt ( def, _) if def. is_enum ( ) => {
390- if def. all_fields ( ) . any ( |item| item. ident . name == variant_field_name) {
399+ if let Some ( field) =
400+ def. all_fields ( ) . find ( |f| f. ident . name == variant_field_name)
401+ {
391402 Ok ( (
392403 ty_res,
393- Some ( UrlFragment :: VariantField {
394- variant : variant_name,
395- field : variant_field_name,
396- } ) ,
404+ Some ( UrlFragment :: Def ( FragmentKind :: VariantField , field. did ) ) ,
397405 ) )
398406 } else {
399407 Err ( ResolutionFailure :: NotResolved {
@@ -430,7 +438,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
430438 . find_by_name_and_namespace ( tcx, Ident :: with_dummy_span ( item_name) , ns, impl_)
431439 . map ( |item| {
432440 let kind = item. kind ;
433- let fragment = UrlFragment :: from_assoc_item ( item_name , kind, false ) ;
441+ let fragment = UrlFragment :: from_assoc_item ( item . def_id , kind, false ) ;
434442 ( Res :: Primitive ( prim_ty) , fragment, Some ( ( kind. as_def_kind ( ) , item. def_id ) ) )
435443 } )
436444 } )
@@ -683,7 +691,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
683691
684692 assoc_item. map ( |item| {
685693 let kind = item. kind ;
686- let fragment = UrlFragment :: from_assoc_item ( item_name , kind, false ) ;
694+ let fragment = UrlFragment :: from_assoc_item ( item . def_id , kind, false ) ;
687695 // HACK(jynelson): `clean` expects the type, not the associated item
688696 // but the disambiguator logic expects the associated item.
689697 // Store the kind in a side channel so that only the disambiguator logic looks at it.
@@ -737,7 +745,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
737745
738746 if let Some ( item) = assoc_item {
739747 let kind = item. kind ;
740- let fragment = UrlFragment :: from_assoc_item ( item_name , kind, false ) ;
748+ let fragment = UrlFragment :: from_assoc_item ( item . def_id , kind, false ) ;
741749 // HACK(jynelson): `clean` expects the type, not the associated item
742750 // but the disambiguator logic expects the associated item.
743751 // Store the kind in a side channel so that only the disambiguator logic looks at it.
@@ -774,7 +782,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
774782 . find ( |item| item. ident . name == item_name) ?;
775783 Some ( (
776784 root_res,
777- UrlFragment :: StructField ( field. ident . name ) ,
785+ UrlFragment :: Def ( FragmentKind :: StructField , field. did ) ,
778786 Some ( ( DefKind :: Field , field. did ) ) ,
779787 ) )
780788 }
@@ -783,7 +791,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
783791 . find_by_name_and_namespace ( tcx, Ident :: with_dummy_span ( item_name) , ns, did)
784792 . map ( |item| {
785793 let fragment = UrlFragment :: from_assoc_item (
786- item_name ,
794+ item . def_id ,
787795 item. kind ,
788796 !item. defaultness . has_value ( ) ,
789797 ) ;
@@ -919,8 +927,6 @@ fn is_derive_trait_collision<T>(ns: &PerNS<Result<(Res, T), ResolutionFailure<'_
919927
920928impl < ' a , ' tcx > DocVisitor for LinkCollector < ' a , ' tcx > {
921929 fn visit_item ( & mut self , item : & Item ) {
922- use rustc_middle:: ty:: DefIdTree ;
923-
924930 let parent_node =
925931 item. def_id . as_def_id ( ) . and_then ( |did| find_nearest_parent_module ( self . cx . tcx , did) ) ;
926932 if parent_node. is_some ( ) {
@@ -2280,14 +2286,12 @@ fn handle_variant(
22802286 cx : & DocContext < ' _ > ,
22812287 res : Res ,
22822288) -> Result < ( Res , Option < UrlFragment > ) , ErrorKind < ' static > > {
2283- use rustc_middle:: ty:: DefIdTree ;
2284-
22852289 cx. tcx
22862290 . parent ( res. def_id ( cx. tcx ) )
22872291 . map ( |parent| {
22882292 let parent_def = Res :: Def ( DefKind :: Enum , parent) ;
22892293 let variant = cx. tcx . expect_variant_res ( res. as_hir_res ( ) . unwrap ( ) ) ;
2290- ( parent_def, Some ( UrlFragment :: Variant ( variant. ident . name ) ) )
2294+ ( parent_def, Some ( UrlFragment :: Def ( FragmentKind :: Variant , variant. def_id ) ) )
22912295 } )
22922296 . ok_or_else ( || ResolutionFailure :: NoParentItem . into ( ) )
22932297}
0 commit comments