@@ -118,6 +118,69 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
118
118
}
119
119
TaitInBodyFinder { collector : self } . visit_expr ( body) ;
120
120
}
121
+
122
+ fn visit_opaque_ty ( & mut self , alias_ty : & ty:: AliasTy < ' tcx > ) {
123
+ if !self . seen . insert ( alias_ty. def_id . expect_local ( ) ) {
124
+ return ;
125
+ }
126
+
127
+ // TAITs outside their defining scopes are ignored.
128
+ let origin = self . tcx . opaque_type_origin ( alias_ty. def_id . expect_local ( ) ) ;
129
+ trace ! ( ?origin) ;
130
+ match origin {
131
+ rustc_hir:: OpaqueTyOrigin :: FnReturn ( _) | rustc_hir:: OpaqueTyOrigin :: AsyncFn ( _) => { }
132
+ rustc_hir:: OpaqueTyOrigin :: TyAlias { in_assoc_ty } => {
133
+ if !in_assoc_ty {
134
+ if !self . check_tait_defining_scope ( alias_ty. def_id . expect_local ( ) ) {
135
+ return ;
136
+ }
137
+ }
138
+ }
139
+ }
140
+
141
+ self . opaques . push ( alias_ty. def_id . expect_local ( ) ) ;
142
+
143
+ let parent_count = self . tcx . generics_of ( alias_ty. def_id ) . parent_count ;
144
+ // Only check that the parent generics of the TAIT/RPIT are unique.
145
+ // the args owned by the opaque are going to always be duplicate
146
+ // lifetime params for RPITs, and empty for TAITs.
147
+ match self
148
+ . tcx
149
+ . uses_unique_generic_params ( & alias_ty. args [ ..parent_count] , CheckRegions :: FromFunction )
150
+ {
151
+ Ok ( ( ) ) => {
152
+ // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
153
+ // supported at all, so this is sound to do, but once we want to support them, you'll
154
+ // start seeing the error below.
155
+
156
+ // Collect opaque types nested within the associated type bounds of this opaque type.
157
+ // We use identity args here, because we already know that the opaque type uses
158
+ // only generic parameters, and thus substituting would not give us more information.
159
+ for ( pred, span) in self
160
+ . tcx
161
+ . explicit_item_bounds ( alias_ty. def_id )
162
+ . instantiate_identity_iter_copied ( )
163
+ {
164
+ trace ! ( ?pred) ;
165
+ self . visit_spanned ( span, pred) ;
166
+ }
167
+ }
168
+ Err ( NotUniqueParam :: NotParam ( arg) ) => {
169
+ self . tcx . dcx ( ) . emit_err ( NotParam {
170
+ arg,
171
+ span : self . span ( ) ,
172
+ opaque_span : self . tcx . def_span ( alias_ty. def_id ) ,
173
+ } ) ;
174
+ }
175
+ Err ( NotUniqueParam :: DuplicateParam ( arg) ) => {
176
+ self . tcx . dcx ( ) . emit_err ( DuplicateArg {
177
+ arg,
178
+ span : self . span ( ) ,
179
+ opaque_span : self . tcx . def_span ( alias_ty. def_id ) ,
180
+ } ) ;
181
+ }
182
+ }
183
+ }
121
184
}
122
185
123
186
impl < ' tcx > super :: sig_types:: SpannedTypeVisitor < ' tcx > for OpaqueTypeCollector < ' tcx > {
@@ -134,67 +197,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
134
197
t. super_visit_with ( self ) ?;
135
198
match t. kind ( ) {
136
199
ty:: Alias ( ty:: Opaque , alias_ty) if alias_ty. def_id . is_local ( ) => {
137
- if !self . seen . insert ( alias_ty. def_id . expect_local ( ) ) {
138
- return ControlFlow :: Continue ( ( ) ) ;
139
- }
140
-
141
- // TAITs outside their defining scopes are ignored.
142
- let origin = self . tcx . opaque_type_origin ( alias_ty. def_id . expect_local ( ) ) ;
143
- trace ! ( ?origin) ;
144
- match origin {
145
- rustc_hir:: OpaqueTyOrigin :: FnReturn ( _)
146
- | rustc_hir:: OpaqueTyOrigin :: AsyncFn ( _) => { }
147
- rustc_hir:: OpaqueTyOrigin :: TyAlias { in_assoc_ty } => {
148
- if !in_assoc_ty {
149
- if !self . check_tait_defining_scope ( alias_ty. def_id . expect_local ( ) ) {
150
- return ControlFlow :: Continue ( ( ) ) ;
151
- }
152
- }
153
- }
154
- }
155
-
156
- self . opaques . push ( alias_ty. def_id . expect_local ( ) ) ;
157
-
158
- let parent_count = self . tcx . generics_of ( alias_ty. def_id ) . parent_count ;
159
- // Only check that the parent generics of the TAIT/RPIT are unique.
160
- // the args owned by the opaque are going to always be duplicate
161
- // lifetime params for RPITs, and empty for TAITs.
162
- match self . tcx . uses_unique_generic_params (
163
- & alias_ty. args [ ..parent_count] ,
164
- CheckRegions :: FromFunction ,
165
- ) {
166
- Ok ( ( ) ) => {
167
- // FIXME: implement higher kinded lifetime bounds on nested opaque types. They are not
168
- // supported at all, so this is sound to do, but once we want to support them, you'll
169
- // start seeing the error below.
170
-
171
- // Collect opaque types nested within the associated type bounds of this opaque type.
172
- // We use identity args here, because we already know that the opaque type uses
173
- // only generic parameters, and thus substituting would not give us more information.
174
- for ( pred, span) in self
175
- . tcx
176
- . explicit_item_bounds ( alias_ty. def_id )
177
- . instantiate_identity_iter_copied ( )
178
- {
179
- trace ! ( ?pred) ;
180
- self . visit_spanned ( span, pred) ;
181
- }
182
- }
183
- Err ( NotUniqueParam :: NotParam ( arg) ) => {
184
- self . tcx . dcx ( ) . emit_err ( NotParam {
185
- arg,
186
- span : self . span ( ) ,
187
- opaque_span : self . tcx . def_span ( alias_ty. def_id ) ,
188
- } ) ;
189
- }
190
- Err ( NotUniqueParam :: DuplicateParam ( arg) ) => {
191
- self . tcx . dcx ( ) . emit_err ( DuplicateArg {
192
- arg,
193
- span : self . span ( ) ,
194
- opaque_span : self . tcx . def_span ( alias_ty. def_id ) ,
195
- } ) ;
196
- }
197
- }
200
+ self . visit_opaque_ty ( alias_ty) ;
198
201
}
199
202
ty:: Alias ( ty:: Weak , alias_ty) if alias_ty. def_id . is_local ( ) => {
200
203
self . tcx
@@ -272,6 +275,91 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
272
275
}
273
276
}
274
277
278
+ struct ImplTraitInAssocTypeCollector < ' tcx > ( OpaqueTypeCollector < ' tcx > ) ;
279
+
280
+ impl < ' tcx > super :: sig_types:: SpannedTypeVisitor < ' tcx > for ImplTraitInAssocTypeCollector < ' tcx > {
281
+ #[ instrument( skip( self ) , ret, level = "trace" ) ]
282
+ fn visit ( & mut self , span : Span , value : impl TypeVisitable < TyCtxt < ' tcx > > ) -> ControlFlow < !> {
283
+ let old = self . 0 . span ;
284
+ self . 0 . span = Some ( span) ;
285
+ value. visit_with ( self ) ;
286
+ self . 0 . span = old;
287
+
288
+ ControlFlow :: Continue ( ( ) )
289
+ }
290
+ }
291
+
292
+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for ImplTraitInAssocTypeCollector < ' tcx > {
293
+ #[ instrument( skip( self ) , ret, level = "trace" ) ]
294
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) -> ControlFlow < !> {
295
+ t. super_visit_with ( self ) ?;
296
+ match t. kind ( ) {
297
+ ty:: Alias ( ty:: Opaque , alias_ty) if alias_ty. def_id . is_local ( ) => {
298
+ self . 0 . visit_opaque_ty ( alias_ty) ;
299
+ }
300
+ ty:: Alias ( ty:: Projection , alias_ty) => {
301
+ // This avoids having to do normalization of `Self::AssocTy` by only
302
+ // supporting the case of a method defining opaque types from assoc types
303
+ // in the same impl block.
304
+ let parent_trait_ref = self
305
+ . 0
306
+ . parent_trait_ref ( )
307
+ . expect ( "impl trait in assoc type collector used on non-assoc item" ) ;
308
+ // If the trait ref of the associated item and the impl differs,
309
+ // then we can't use the impl's identity substitutions below, so
310
+ // just skip.
311
+ if alias_ty. trait_ref ( self . 0 . tcx ) == parent_trait_ref {
312
+ let parent = self . 0 . parent ( ) . expect ( "we should have a parent here" ) ;
313
+
314
+ for & assoc in self . 0 . tcx . associated_items ( parent) . in_definition_order ( ) {
315
+ trace ! ( ?assoc) ;
316
+ if assoc. trait_item_def_id != Some ( alias_ty. def_id ) {
317
+ continue ;
318
+ }
319
+
320
+ // If the type is further specializable, then the type_of
321
+ // is not actually correct below.
322
+ if !assoc. defaultness ( self . 0 . tcx ) . is_final ( ) {
323
+ continue ;
324
+ }
325
+
326
+ let impl_args = alias_ty. args . rebase_onto (
327
+ self . 0 . tcx ,
328
+ parent_trait_ref. def_id ,
329
+ ty:: GenericArgs :: identity_for_item ( self . 0 . tcx , parent) ,
330
+ ) ;
331
+
332
+ if check_args_compatible ( self . 0 . tcx , assoc, impl_args) {
333
+ return self
334
+ . 0
335
+ . tcx
336
+ . type_of ( assoc. def_id )
337
+ . instantiate ( self . 0 . tcx , impl_args)
338
+ . visit_with ( self ) ;
339
+ } else {
340
+ self . 0 . tcx . dcx ( ) . span_delayed_bug (
341
+ self . 0 . tcx . def_span ( assoc. def_id ) ,
342
+ "item had incorrect args" ,
343
+ ) ;
344
+ }
345
+ }
346
+ }
347
+ }
348
+ _ => trace ! ( kind=?t. kind( ) ) ,
349
+ }
350
+ ControlFlow :: Continue ( ( ) )
351
+ }
352
+ }
353
+
354
+ fn impl_trait_in_assoc_types_defined_by < ' tcx > (
355
+ tcx : TyCtxt < ' tcx > ,
356
+ item : LocalDefId ,
357
+ ) -> & ' tcx ty:: List < LocalDefId > {
358
+ let mut collector = ImplTraitInAssocTypeCollector ( OpaqueTypeCollector :: new ( tcx, item) ) ;
359
+ super :: sig_types:: walk_types ( tcx, item, & mut collector) ;
360
+ tcx. mk_local_def_ids ( & collector. 0 . opaques )
361
+ }
362
+
275
363
fn opaque_types_defined_by < ' tcx > (
276
364
tcx : TyCtxt < ' tcx > ,
277
365
item : LocalDefId ,
@@ -321,5 +409,6 @@ fn opaque_types_defined_by<'tcx>(
321
409
}
322
410
323
411
pub ( super ) fn provide ( providers : & mut Providers ) {
324
- * providers = Providers { opaque_types_defined_by, ..* providers } ;
412
+ * providers =
413
+ Providers { opaque_types_defined_by, impl_trait_in_assoc_types_defined_by, ..* providers } ;
325
414
}
0 commit comments