1
+ use std:: collections:: hash_map:: Entry ;
2
+
3
+ use rustc_data_structures:: fx:: FxHashMap ;
1
4
use rustc_hir as hir;
2
5
use rustc_hir:: def:: DefKind ;
3
6
use rustc_hir:: def_id:: { DefId , DefIdMap , LocalDefId } ;
@@ -6,12 +9,14 @@ use rustc_hir::intravisit::{self, Visitor};
6
9
use rustc_middle:: query:: Providers ;
7
10
use rustc_middle:: ty:: { self , ImplTraitInTraitData , TyCtxt } ;
8
11
use rustc_middle:: { bug, span_bug} ;
12
+ use rustc_span:: Symbol ;
9
13
10
14
pub ( crate ) fn provide ( providers : & mut Providers ) {
11
15
* providers = Providers {
12
16
associated_item,
13
17
associated_item_def_ids,
14
18
associated_items,
19
+ associated_types_for_impl_traits_in_trait,
15
20
associated_types_for_impl_traits_in_associated_fn,
16
21
impl_item_implementor_ids,
17
22
..* providers
@@ -163,10 +168,12 @@ struct RPITVisitor<'tcx> {
163
168
synthetics : Vec < LocalDefId > ,
164
169
data : DefPathData ,
165
170
disambiguator : DisambiguatorState ,
171
+ depth : u32 ,
166
172
}
167
173
168
174
impl < ' tcx > Visitor < ' tcx > for RPITVisitor < ' tcx > {
169
175
fn visit_opaque_ty ( & mut self , opaque : & ' tcx hir:: OpaqueTy < ' tcx > ) -> Self :: Result {
176
+ self . depth += 1 ;
170
177
self . synthetics . push ( associated_type_for_impl_trait_in_trait (
171
178
self . tcx ,
172
179
opaque. def_id ,
@@ -177,17 +184,6 @@ impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> {
177
184
}
178
185
}
179
186
180
- struct DisambiguatorIdxVisitor {
181
- depth : u32 ,
182
- }
183
-
184
- impl < ' tcx > Visitor < ' tcx > for DisambiguatorIdxVisitor {
185
- fn visit_opaque_ty ( & mut self , opaque : & ' tcx hir:: OpaqueTy < ' tcx > ) -> Self :: Result {
186
- self . depth += 1 ;
187
- intravisit:: walk_opaque_ty ( self , opaque)
188
- }
189
- }
190
-
191
187
/// Given an `fn_def_id` of a trait or a trait implementation:
192
188
///
193
189
/// if `fn_def_id` is a function defined inside a trait, then it synthesizes
@@ -205,51 +201,7 @@ fn associated_types_for_impl_traits_in_associated_fn(
205
201
206
202
match tcx. def_kind ( parent_def_id) {
207
203
DefKind :: Trait => {
208
- if let Some ( output) = tcx. hir_get_fn_output ( fn_def_id) {
209
- let def_path_id = |def_id : LocalDefId | tcx. item_name ( def_id. to_def_id ( ) ) ;
210
- let def_path_data = def_path_id ( fn_def_id) ;
211
-
212
- let ( .., trait_item_refs) = tcx. hir_expect_item ( parent_def_id) . expect_trait ( ) ;
213
- // The purpose of `disambiguator_idx` is to ensure there are
214
- // no duplicate `def_id` in certain cases, such as:
215
- // ```
216
- // trait Foo {
217
- // fn bar() -> impl Trait;
218
- // fn bar() -> impl Trait;
219
- // // ~~~~~~~~~~ It will generate the same ID if we don’t disambiguate it.
220
- // }
221
- // ```
222
- let disambiguator_idx = trait_item_refs
223
- . iter ( )
224
- . take_while ( |item| item. id . owner_id . def_id != fn_def_id)
225
- . filter ( |item| {
226
- matches ! ( item. kind, hir:: AssocItemKind :: Fn { .. } )
227
- && def_path_id ( item. id . owner_id . def_id ) == def_path_data
228
- } )
229
- . last ( )
230
- . map ( |item| {
231
- let output = tcx. hir_get_fn_output ( item. id . owner_id . def_id ) . unwrap ( ) ;
232
- let mut visitor = DisambiguatorIdxVisitor { depth : 0 } ;
233
- visitor. visit_fn_ret_ty ( output) ;
234
- tcx. def_key ( item. id . owner_id . def_id ) . disambiguated_data . disambiguator
235
- + visitor. depth
236
- } )
237
- . unwrap_or_default ( ) ;
238
-
239
- let data = DefPathData :: AnonAssocTy ( def_path_data) ;
240
- let mut visitor = RPITVisitor {
241
- tcx,
242
- synthetics : vec ! [ ] ,
243
- data,
244
- disambiguator : DisambiguatorState :: with ( parent_def_id, data, disambiguator_idx) ,
245
- } ;
246
- visitor. visit_fn_ret_ty ( output) ;
247
- tcx. arena . alloc_from_iter (
248
- visitor. synthetics . into_iter ( ) . map ( |def_id| def_id. to_def_id ( ) ) ,
249
- )
250
- } else {
251
- & [ ]
252
- }
204
+ tcx. associated_types_for_impl_traits_in_trait ( parent_def_id) [ & fn_def_id. to_def_id ( ) ]
253
205
}
254
206
255
207
DefKind :: Impl { .. } => {
@@ -274,6 +226,54 @@ fn associated_types_for_impl_traits_in_associated_fn(
274
226
}
275
227
}
276
228
229
+ fn associated_types_for_impl_traits_in_trait < ' tcx > (
230
+ tcx : TyCtxt < ' tcx > ,
231
+ trait_id : LocalDefId ,
232
+ ) -> DefIdMap < & ' tcx [ DefId ] > {
233
+ let ( .., trait_item_refs) = tcx. hir_expect_item ( trait_id) . expect_trait ( ) ;
234
+
235
+ let mut disambiguator_idx_map = FxHashMap :: default ( ) ;
236
+ let find_disambiguator_idx = |map : & mut FxHashMap < Symbol , u32 > , name| match map. entry ( name) {
237
+ Entry :: Occupied ( occ) => * occ. get ( ) + 1 ,
238
+ Entry :: Vacant ( vac) => {
239
+ vac. insert ( 0 ) ;
240
+ 0
241
+ }
242
+ } ;
243
+ let update_disambiguator_idx = |map : & mut FxHashMap < Symbol , u32 > , name, offset : u32 | {
244
+ * map. get_mut ( & name) . unwrap ( ) += offset
245
+ } ;
246
+
247
+ trait_item_refs
248
+ . iter ( )
249
+ . filter_map ( move |item| {
250
+ if !matches ! ( item. kind, hir:: AssocItemKind :: Fn { .. } ) {
251
+ return None ;
252
+ }
253
+ let fn_def_id = item. id . owner_id . def_id ;
254
+ let Some ( output) = tcx. hir_get_fn_output ( fn_def_id) else {
255
+ return Some ( ( fn_def_id. to_def_id ( ) , & [ ] as & [ DefId ] ) ) ;
256
+ } ;
257
+ let def_name = tcx. item_name ( fn_def_id. to_def_id ( ) ) ;
258
+ let disambiguator_idx = find_disambiguator_idx ( & mut disambiguator_idx_map, def_name) ;
259
+ let data = DefPathData :: AnonAssocTy ( def_name) ;
260
+ let mut visitor = RPITVisitor {
261
+ tcx,
262
+ synthetics : vec ! [ ] ,
263
+ data,
264
+ depth : 0 ,
265
+ disambiguator : DisambiguatorState :: with ( trait_id, data, disambiguator_idx) ,
266
+ } ;
267
+ visitor. visit_fn_ret_ty ( output) ;
268
+ update_disambiguator_idx ( & mut disambiguator_idx_map, def_name, visitor. depth ) ;
269
+ let defs = tcx
270
+ . arena
271
+ . alloc_from_iter ( visitor. synthetics . into_iter ( ) . map ( |def_id| def_id. to_def_id ( ) ) ) ;
272
+ Some ( ( fn_def_id. to_def_id ( ) , defs) )
273
+ } )
274
+ . collect ( )
275
+ }
276
+
277
277
/// Given an `opaque_ty_def_id` corresponding to an `impl Trait` in an associated
278
278
/// function from a trait, synthesize an associated type for that `impl Trait`
279
279
/// that inherits properties that we infer from the method and the opaque type.
0 commit comments