@@ -56,6 +56,59 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
5656 }
5757 }
5858
59+ fn variant_field (
60+ & self ,
61+ path_str : & str ,
62+ current_item : & Option < String > ,
63+ module_id : syntax:: ast:: NodeId ,
64+ ) -> Result < ( Res , Option < String > ) , ( ) > {
65+ let cx = self . cx ;
66+
67+ let mut split = path_str. rsplitn ( 3 , "::" ) ;
68+ let variant_field_name = split. next ( ) . map ( |f| Symbol :: intern ( f) ) . ok_or ( ( ) ) ?;
69+ let variant_name = split. next ( ) . map ( |f| Symbol :: intern ( f) ) . ok_or ( ( ) ) ?;
70+ let path = split. next ( ) . map ( |f| {
71+ if f == "self" || f == "Self" {
72+ if let Some ( name) = current_item. as_ref ( ) {
73+ return name. clone ( ) ;
74+ }
75+ }
76+ f. to_owned ( )
77+ } ) . ok_or ( ( ) ) ?;
78+ let ( _, ty_res) = cx. enter_resolver ( |resolver| {
79+ resolver. resolve_str_path_error ( DUMMY_SP , & path, TypeNS , module_id)
80+ } ) ?;
81+ if let Res :: Err = ty_res {
82+ return Err ( ( ) ) ;
83+ }
84+ let ty_res = ty_res. map_id ( |_| panic ! ( "unexpected node_id" ) ) ;
85+ match ty_res {
86+ Res :: Def ( DefKind :: Enum , did) => {
87+ let item = cx. tcx . inherent_impls ( did)
88+ . iter ( )
89+ . flat_map ( |imp| cx. tcx . associated_items ( * imp) )
90+ . find ( |item| item. ident . name == variant_name) ;
91+ if item. is_some ( ) {
92+ return Err ( ( ) ) ;
93+ }
94+ match cx. tcx . type_of ( did) . kind {
95+ ty:: Adt ( def, _) if def. is_enum ( ) => {
96+ if def. all_fields ( )
97+ . find ( |item| item. ident . name == variant_field_name) . is_some ( ) {
98+ Ok ( ( ty_res,
99+ Some ( format ! ( "variant.{}.field.{}" ,
100+ variant_name, variant_field_name) ) ) )
101+ } else {
102+ Err ( ( ) )
103+ }
104+ }
105+ _ => Err ( ( ) ) ,
106+ }
107+ }
108+ _ => Err ( ( ) )
109+ }
110+ }
111+
59112 /// Resolves a string as a path within a particular namespace. Also returns an optional
60113 /// URL fragment in the case of variants and methods.
61114 fn resolve (
@@ -149,7 +202,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
149202 resolver. resolve_str_path_error ( DUMMY_SP , & path, TypeNS , module_id)
150203 } ) . map_err ( |_| ErrorKind :: ResolutionFailure ) ?;
151204 if let Res :: Err = ty_res {
152- return Err ( ErrorKind :: ResolutionFailure ) ;
205+ return self . variant_field ( path_str , current_item , module_id ) ;
153206 }
154207 let ty_res = ty_res. map_id ( |_| panic ! ( "unexpected node_id" ) ) ;
155208 match ty_res {
@@ -165,7 +218,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
165218 let out = match item. kind {
166219 ty:: AssocKind :: Method if ns == ValueNS => "method" ,
167220 ty:: AssocKind :: Const if ns == ValueNS => "associatedconstant" ,
168- _ => return Err ( ErrorKind :: ResolutionFailure )
221+ _ => return self . variant_field ( path_str , current_item , module_id ) ,
169222 } ;
170223 if extra_fragment. is_some ( ) {
171224 Err ( ErrorKind :: AnchorFailure (
@@ -206,10 +259,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
206259 item. ident) ) ) )
207260 }
208261 } else {
209- Err ( ErrorKind :: ResolutionFailure )
262+ self . variant_field ( path_str , current_item , module_id )
210263 }
211264 }
212- _ => Err ( ErrorKind :: ResolutionFailure ) ,
265+ _ => self . variant_field ( path_str , current_item , module_id ) ,
213266 }
214267 }
215268 }
@@ -228,7 +281,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
228281 "tymethod"
229282 }
230283 }
231- _ => return Err ( ErrorKind :: ResolutionFailure )
284+ _ => return self . variant_field ( path_str , current_item , module_id ) ,
232285 } ;
233286
234287 if extra_fragment. is_some ( ) {
@@ -244,10 +297,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
244297 Ok ( ( ty_res, Some ( format ! ( "{}.{}" , kind, item_name) ) ) )
245298 }
246299 } else {
247- Err ( ErrorKind :: ResolutionFailure )
300+ self . variant_field ( path_str , current_item , module_id )
248301 }
249302 }
250- _ => Err ( ErrorKind :: ResolutionFailure )
303+ _ => self . variant_field ( path_str , current_item , module_id ) ,
251304 }
252305 } else {
253306 debug ! ( "attempting to resolve item without parent module: {}" , path_str) ;
0 commit comments