@@ -56,6 +56,64 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
56
56
}
57
57
}
58
58
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 > ) , ErrorKind > {
65
+ let cx = self . cx ;
66
+
67
+ let mut split = path_str. rsplitn ( 3 , "::" ) ;
68
+ let variant_field_name = split
69
+ . next ( )
70
+ . map ( |f| Symbol :: intern ( f) )
71
+ . ok_or ( ErrorKind :: ResolutionFailure ) ?;
72
+ let variant_name = split
73
+ . next ( )
74
+ . map ( |f| Symbol :: intern ( f) )
75
+ . ok_or ( ErrorKind :: ResolutionFailure ) ?;
76
+ let path = split. next ( ) . map ( |f| {
77
+ if f == "self" || f == "Self" {
78
+ if let Some ( name) = current_item. as_ref ( ) {
79
+ return name. clone ( ) ;
80
+ }
81
+ }
82
+ f. to_owned ( )
83
+ } ) . ok_or ( ErrorKind :: ResolutionFailure ) ?;
84
+ let ( _, ty_res) = cx. enter_resolver ( |resolver| {
85
+ resolver. resolve_str_path_error ( DUMMY_SP , & path, TypeNS , module_id)
86
+ } ) . map_err ( |_| ErrorKind :: ResolutionFailure ) ?;
87
+ if let Res :: Err = ty_res {
88
+ return Err ( ErrorKind :: ResolutionFailure ) ;
89
+ }
90
+ let ty_res = ty_res. map_id ( |_| panic ! ( "unexpected node_id" ) ) ;
91
+ match ty_res {
92
+ Res :: Def ( DefKind :: Enum , did) => {
93
+ if cx. tcx . inherent_impls ( did)
94
+ . iter ( )
95
+ . flat_map ( |imp| cx. tcx . associated_items ( * imp) )
96
+ . any ( |item| item. ident . name == variant_name) {
97
+ return Err ( ErrorKind :: ResolutionFailure ) ;
98
+ }
99
+ match cx. tcx . type_of ( did) . kind {
100
+ ty:: Adt ( def, _) if def. is_enum ( ) => {
101
+ if def. all_fields ( )
102
+ . any ( |item| item. ident . name == variant_field_name) {
103
+ Ok ( ( ty_res,
104
+ Some ( format ! ( "variant.{}.field.{}" ,
105
+ variant_name, variant_field_name) ) ) )
106
+ } else {
107
+ Err ( ErrorKind :: ResolutionFailure )
108
+ }
109
+ }
110
+ _ => Err ( ErrorKind :: ResolutionFailure ) ,
111
+ }
112
+ }
113
+ _ => Err ( ErrorKind :: ResolutionFailure )
114
+ }
115
+ }
116
+
59
117
/// Resolves a string as a path within a particular namespace. Also returns an optional
60
118
/// URL fragment in the case of variants and methods.
61
119
fn resolve (
@@ -121,23 +179,18 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
121
179
122
180
// Try looking for methods and associated items.
123
181
let mut split = path_str. rsplitn ( 2 , "::" ) ;
124
- let item_name = if let Some ( first) = split. next ( ) {
125
- Symbol :: intern ( first)
126
- } else {
127
- return Err ( ErrorKind :: ResolutionFailure )
128
- } ;
129
-
130
- let mut path = if let Some ( second) = split. next ( ) {
131
- second. to_owned ( )
132
- } else {
133
- return Err ( ErrorKind :: ResolutionFailure )
134
- } ;
135
-
136
- if path == "self" || path == "Self" {
137
- if let Some ( name) = current_item. as_ref ( ) {
138
- path = name. clone ( ) ;
182
+ let item_name = split. next ( )
183
+ . map ( |f| Symbol :: intern ( f) )
184
+ . ok_or ( ErrorKind :: ResolutionFailure ) ?;
185
+ let path = split. next ( ) . map ( |f| {
186
+ if f == "self" || f == "Self" {
187
+ if let Some ( name) = current_item. as_ref ( ) {
188
+ return name. clone ( ) ;
189
+ }
139
190
}
140
- }
191
+ f. to_owned ( )
192
+ } ) . ok_or ( ErrorKind :: ResolutionFailure ) ?;
193
+
141
194
if let Some ( prim) = is_primitive ( & path, TypeNS ) {
142
195
let did = primitive_impl ( cx, & path) . ok_or ( ErrorKind :: ResolutionFailure ) ?;
143
196
return cx. tcx . associated_items ( did)
@@ -154,7 +207,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
154
207
resolver. resolve_str_path_error ( DUMMY_SP , & path, TypeNS , module_id)
155
208
} ) . map_err ( |_| ErrorKind :: ResolutionFailure ) ?;
156
209
if let Res :: Err = ty_res {
157
- return Err ( ErrorKind :: ResolutionFailure ) ;
210
+ return self . variant_field ( path_str , current_item , module_id ) ;
158
211
}
159
212
let ty_res = ty_res. map_id ( |_| panic ! ( "unexpected node_id" ) ) ;
160
213
match ty_res {
@@ -170,7 +223,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
170
223
let out = match item. kind {
171
224
ty:: AssocKind :: Method if ns == ValueNS => "method" ,
172
225
ty:: AssocKind :: Const if ns == ValueNS => "associatedconstant" ,
173
- _ => return Err ( ErrorKind :: ResolutionFailure )
226
+ _ => return self . variant_field ( path_str , current_item , module_id ) ,
174
227
} ;
175
228
if extra_fragment. is_some ( ) {
176
229
Err ( ErrorKind :: AnchorFailure (
@@ -211,10 +264,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
211
264
item. ident) ) ) )
212
265
}
213
266
} else {
214
- Err ( ErrorKind :: ResolutionFailure )
267
+ self . variant_field ( path_str , current_item , module_id )
215
268
}
216
269
}
217
- _ => Err ( ErrorKind :: ResolutionFailure ) ,
270
+ _ => self . variant_field ( path_str , current_item , module_id ) ,
218
271
}
219
272
}
220
273
}
@@ -233,7 +286,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
233
286
"tymethod"
234
287
}
235
288
}
236
- _ => return Err ( ErrorKind :: ResolutionFailure )
289
+ _ => return self . variant_field ( path_str , current_item , module_id ) ,
237
290
} ;
238
291
239
292
if extra_fragment. is_some ( ) {
@@ -249,10 +302,10 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
249
302
Ok ( ( ty_res, Some ( format ! ( "{}.{}" , kind, item_name) ) ) )
250
303
}
251
304
} else {
252
- Err ( ErrorKind :: ResolutionFailure )
305
+ self . variant_field ( path_str , current_item , module_id )
253
306
}
254
307
}
255
- _ => Err ( ErrorKind :: ResolutionFailure )
308
+ _ => self . variant_field ( path_str , current_item , module_id ) ,
256
309
}
257
310
} else {
258
311
debug ! ( "attempting to resolve item without parent module: {}" , path_str) ;
0 commit comments