@@ -77,101 +77,104 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
7777 for ( pred, pred_span) in
7878 cx. tcx . explicit_item_bounds ( def_id) . instantiate_identity_iter_copied ( )
7979 {
80- let predicate = infcx. instantiate_binder_with_placeholders ( pred. kind ( ) ) ;
81- let ty:: ClauseKind :: Projection ( proj) = predicate else {
82- continue ;
83- } ;
84- // Only check types, since those are the only things that may
85- // have opaques in them anyways.
86- let Some ( proj_term) = proj. term . ty ( ) else { continue } ;
80+ infcx. enter_forall ( pred. kind ( ) , |predicate| {
81+ let ty:: ClauseKind :: Projection ( proj) = predicate else {
82+ return ;
83+ } ;
84+ // Only check types, since those are the only things that may
85+ // have opaques in them anyways.
86+ let Some ( proj_term) = proj. term . ty ( ) else { return } ;
8787
88- // HACK: `impl Trait<Assoc = impl Trait2>` from an RPIT is "ok"...
89- if let ty:: Alias ( ty:: Opaque , opaque_ty) = * proj_term. kind ( )
90- && cx. tcx . parent ( opaque_ty. def_id ) == def_id
91- && matches ! (
92- opaque. origin,
93- hir:: OpaqueTyOrigin :: FnReturn ( _) | hir:: OpaqueTyOrigin :: AsyncFn ( _)
94- )
95- {
96- continue ;
97- }
88+ // HACK: `impl Trait<Assoc = impl Trait2>` from an RPIT is "ok"...
89+ if let ty:: Alias ( ty:: Opaque , opaque_ty) = * proj_term. kind ( )
90+ && cx. tcx . parent ( opaque_ty. def_id ) == def_id
91+ && matches ! (
92+ opaque. origin,
93+ hir:: OpaqueTyOrigin :: FnReturn ( _) | hir:: OpaqueTyOrigin :: AsyncFn ( _)
94+ )
95+ {
96+ return ;
97+ }
9898
99- // HACK: `async fn() -> Self` in traits is "ok"...
100- // This is not really that great, but it's similar to why the `-> Self`
101- // return type is well-formed in traits even when `Self` isn't sized.
102- if let ty:: Param ( param_ty) = * proj_term. kind ( )
103- && param_ty. name == kw:: SelfUpper
104- && matches ! ( opaque. origin, hir:: OpaqueTyOrigin :: AsyncFn ( _) )
105- && opaque. in_trait
106- {
107- continue ;
108- }
99+ // HACK: `async fn() -> Self` in traits is "ok"...
100+ // This is not really that great, but it's similar to why the `-> Self`
101+ // return type is well-formed in traits even when `Self` isn't sized.
102+ if let ty:: Param ( param_ty) = * proj_term. kind ( )
103+ && param_ty. name == kw:: SelfUpper
104+ && matches ! ( opaque. origin, hir:: OpaqueTyOrigin :: AsyncFn ( _) )
105+ && opaque. in_trait
106+ {
107+ return ;
108+ }
109109
110- let proj_ty =
111- Ty :: new_projection ( cx. tcx , proj. projection_ty . def_id , proj. projection_ty . args ) ;
112- // For every instance of the projection type in the bounds,
113- // replace them with the term we're assigning to the associated
114- // type in our opaque type.
115- let proj_replacer = & mut BottomUpFolder {
116- tcx : cx. tcx ,
117- ty_op : |ty| if ty == proj_ty { proj_term } else { ty } ,
118- lt_op : |lt| lt,
119- ct_op : |ct| ct,
120- } ;
121- // For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`,
122- // e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait`
123- // with `impl Send: OtherTrait`.
124- for ( assoc_pred, assoc_pred_span) in cx
125- . tcx
126- . explicit_item_bounds ( proj. projection_ty . def_id )
127- . iter_instantiated_copied ( cx. tcx , proj. projection_ty . args )
128- {
129- let assoc_pred = assoc_pred. fold_with ( proj_replacer) ;
130- let Ok ( assoc_pred) = traits:: fully_normalize (
131- infcx,
132- traits:: ObligationCause :: dummy ( ) ,
133- cx. param_env ,
134- assoc_pred,
135- ) else {
136- continue ;
110+ let proj_ty =
111+ Ty :: new_projection ( cx. tcx , proj. projection_ty . def_id , proj. projection_ty . args ) ;
112+ // For every instance of the projection type in the bounds,
113+ // replace them with the term we're assigning to the associated
114+ // type in our opaque type.
115+ let proj_replacer = & mut BottomUpFolder {
116+ tcx : cx. tcx ,
117+ ty_op : |ty| if ty == proj_ty { proj_term } else { ty } ,
118+ lt_op : |lt| lt,
119+ ct_op : |ct| ct,
137120 } ;
138- // If that predicate doesn't hold modulo regions (but passed during type-check),
139- // then we must've taken advantage of the hack in `project_and_unify_types` where
140- // we replace opaques with inference vars. Emit a warning!
141- if !infcx. predicate_must_hold_modulo_regions ( & traits:: Obligation :: new (
142- cx. tcx ,
143- traits:: ObligationCause :: dummy ( ) ,
144- cx. param_env ,
145- assoc_pred,
146- ) ) {
147- // If it's a trait bound and an opaque that doesn't satisfy it,
148- // then we can emit a suggestion to add the bound.
149- let add_bound = match ( proj_term. kind ( ) , assoc_pred. kind ( ) . skip_binder ( ) ) {
150- (
151- ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, .. } ) ,
152- ty:: ClauseKind :: Trait ( trait_pred) ,
153- ) => Some ( AddBound {
154- suggest_span : cx. tcx . def_span ( * def_id) . shrink_to_hi ( ) ,
155- trait_ref : trait_pred. print_modifiers_and_trait_path ( ) ,
156- } ) ,
157- _ => None ,
121+ // For example, in `impl Trait<Assoc = impl Send>`, for all of the bounds on `Assoc`,
122+ // e.g. `type Assoc: OtherTrait`, replace `<impl Trait as Trait>::Assoc: OtherTrait`
123+ // with `impl Send: OtherTrait`.
124+ for ( assoc_pred, assoc_pred_span) in cx
125+ . tcx
126+ . explicit_item_bounds ( proj. projection_ty . def_id )
127+ . iter_instantiated_copied ( cx. tcx , proj. projection_ty . args )
128+ {
129+ let assoc_pred = assoc_pred. fold_with ( proj_replacer) ;
130+ let Ok ( assoc_pred) = traits:: fully_normalize (
131+ infcx,
132+ traits:: ObligationCause :: dummy ( ) ,
133+ cx. param_env ,
134+ assoc_pred,
135+ ) else {
136+ continue ;
158137 } ;
159- cx. emit_span_lint (
160- OPAQUE_HIDDEN_INFERRED_BOUND ,
161- pred_span,
162- OpaqueHiddenInferredBoundLint {
163- ty : Ty :: new_opaque (
164- cx. tcx ,
165- def_id,
166- ty:: GenericArgs :: identity_for_item ( cx. tcx , def_id) ,
167- ) ,
168- proj_ty : proj_term,
169- assoc_pred_span,
170- add_bound,
171- } ,
172- ) ;
138+
139+ // If that predicate doesn't hold modulo regions (but passed during type-check),
140+ // then we must've taken advantage of the hack in `project_and_unify_types` where
141+ // we replace opaques with inference vars. Emit a warning!
142+ if !infcx. predicate_must_hold_modulo_regions ( & traits:: Obligation :: new (
143+ cx. tcx ,
144+ traits:: ObligationCause :: dummy ( ) ,
145+ cx. param_env ,
146+ assoc_pred,
147+ ) ) {
148+ // If it's a trait bound and an opaque that doesn't satisfy it,
149+ // then we can emit a suggestion to add the bound.
150+ let add_bound = match ( proj_term. kind ( ) , assoc_pred. kind ( ) . skip_binder ( ) ) {
151+ (
152+ ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, .. } ) ,
153+ ty:: ClauseKind :: Trait ( trait_pred) ,
154+ ) => Some ( AddBound {
155+ suggest_span : cx. tcx . def_span ( * def_id) . shrink_to_hi ( ) ,
156+ trait_ref : trait_pred. print_modifiers_and_trait_path ( ) ,
157+ } ) ,
158+ _ => None ,
159+ } ;
160+
161+ cx. emit_span_lint (
162+ OPAQUE_HIDDEN_INFERRED_BOUND ,
163+ pred_span,
164+ OpaqueHiddenInferredBoundLint {
165+ ty : Ty :: new_opaque (
166+ cx. tcx ,
167+ def_id,
168+ ty:: GenericArgs :: identity_for_item ( cx. tcx , def_id) ,
169+ ) ,
170+ proj_ty : proj_term,
171+ assoc_pred_span,
172+ add_bound,
173+ } ,
174+ ) ;
175+ }
173176 }
174- }
177+ } ) ;
175178 }
176179 }
177180}
0 commit comments