@@ -77,101 +77,104 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
77
77
for ( pred, pred_span) in
78
78
cx. tcx . explicit_item_bounds ( def_id) . instantiate_identity_iter_copied ( )
79
79
{
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 } ;
87
87
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
+ }
98
98
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
+ }
109
109
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,
137
120
} ;
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 ;
158
137
} ;
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
+ }
173
176
}
174
- }
177
+ } ) ;
175
178
}
176
179
}
177
180
}
0 commit comments