@@ -118,6 +118,69 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
118118 }
119119 TaitInBodyFinder { collector : self } . visit_expr ( body) ;
120120 }
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+ }
121184}
122185
123186impl < ' tcx > super :: sig_types:: SpannedTypeVisitor < ' tcx > for OpaqueTypeCollector < ' tcx > {
@@ -134,67 +197,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
134197 t. super_visit_with ( self ) ?;
135198 match t. kind ( ) {
136199 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) ;
198201 }
199202 ty:: Alias ( ty:: Weak , alias_ty) if alias_ty. def_id . is_local ( ) => {
200203 self . tcx
@@ -272,6 +275,91 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
272275 }
273276}
274277
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+
275363fn opaque_types_defined_by < ' tcx > (
276364 tcx : TyCtxt < ' tcx > ,
277365 item : LocalDefId ,
@@ -321,5 +409,6 @@ fn opaque_types_defined_by<'tcx>(
321409}
322410
323411pub ( 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 } ;
325414}
0 commit comments