@@ -20,7 +20,6 @@ use rustc_infer::infer::{
20
20
} ;
21
21
use rustc_middle:: hir:: place:: PlaceBase ;
22
22
use rustc_middle:: mir:: { ConstraintCategory , ReturnConstraint } ;
23
- use rustc_middle:: traits:: ObligationCause ;
24
23
use rustc_middle:: ty:: GenericArgs ;
25
24
use rustc_middle:: ty:: TypeVisitor ;
26
25
use rustc_middle:: ty:: { self , RegionVid , Ty } ;
@@ -29,8 +28,7 @@ use rustc_span::symbol::{kw, Ident};
29
28
use rustc_span:: Span ;
30
29
use rustc_trait_selection:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
31
30
use rustc_trait_selection:: infer:: InferCtxtExt ;
32
- use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
33
- use rustc_trait_selection:: traits:: Obligation ;
31
+ use rustc_trait_selection:: traits:: { Obligation , ObligationCtxt } ;
34
32
35
33
use crate :: borrowck_errors;
36
34
use crate :: session_diagnostics:: {
@@ -1140,16 +1138,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
1140
1138
return ;
1141
1139
} ;
1142
1140
1143
- // Get the arguments for the found method, only specifying that `Self` is the receiver type.
1144
- let args = GenericArgs :: for_item ( tcx, method, |param, _| {
1145
- if param. index == 0 {
1146
- possible_rcvr_ty. into ( )
1147
- } else {
1148
- self . infcx . var_for_def ( expr. span , param)
1149
- }
1150
- } ) ;
1151
-
1152
- let preds = tcx. predicates_of ( method) . instantiate ( tcx, args) ;
1153
1141
// Get the type for the parameter corresponding to the argument the closure with the
1154
1142
// lifetime error we had.
1155
1143
let Some ( input) = tcx
@@ -1163,75 +1151,30 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
1163
1151
return ;
1164
1152
} ;
1165
1153
1166
- let cause = ObligationCause :: misc ( expr . span , self . mir_def_id ( ) ) ;
1154
+ trace ! ( ?input ) ;
1167
1155
1168
- enum CanSuggest {
1169
- Yes ,
1170
- No ,
1171
- Maybe ,
1172
- }
1156
+ let ty:: Param ( closure_param) = input. kind ( ) else { return } ;
1173
1157
1174
- // Ok, the following is a HACK. We go over every predicate in the `fn` looking for the ones
1175
- // referencing the argument at hand, which is a closure with some bounds. In those, we
1176
- // re-verify that the closure we synthesized still matches the closure bound on the argument
1177
- // (this is likely unneeded) but *more importantly*, we look at the
1178
- // `<ClosureTy as FnOnce>::Output = ClosureRetTy` to confirm that the closure type we
1179
- // synthesized above *will* be accepted by the `where` bound corresponding to this
1180
- // argument. Put a different way, given `counts.iter().max_by_key(|(_, v)| v)`, we check
1181
- // that a new `ClosureTy` of `|(_, v)| { **v }` will be accepted by this method signature:
1182
- // ```
1183
- // fn max_by_key<B: Ord, F>(self, f: F) -> Option<Self::Item>
1184
- // where
1185
- // Self: Sized,
1186
- // F: FnMut(&Self::Item) -> B,
1187
- // ```
1188
- // Sadly, we can't use `ObligationCtxt` to do this, we need to modify things in place.
1189
- let mut can_suggest = CanSuggest :: Maybe ;
1190
- for pred in preds. predicates {
1191
- match tcx. liberate_late_bound_regions ( self . mir_def_id ( ) . into ( ) , pred. kind ( ) ) {
1192
- ty:: ClauseKind :: Trait ( pred)
1193
- if self . infcx . can_eq ( self . param_env , pred. self_ty ( ) , * input)
1194
- && [
1195
- tcx. lang_items ( ) . fn_trait ( ) ,
1196
- tcx. lang_items ( ) . fn_mut_trait ( ) ,
1197
- tcx. lang_items ( ) . fn_once_trait ( ) ,
1198
- ]
1199
- . contains ( & Some ( pred. def_id ( ) ) ) =>
1200
- {
1201
- // This predicate is an `Fn*` trait and corresponds to the argument with the
1202
- // closure that failed the lifetime check. We verify that the arguments will
1203
- // continue to match (which didn't change, so they should, and this be a no-op).
1204
- let pred = pred. with_self_ty ( tcx, closure_ty) ;
1205
- let o = Obligation :: new ( tcx, cause. clone ( ) , self . param_env , pred) ;
1206
- if !self . infcx . predicate_may_hold ( & o) {
1207
- // The closure we have doesn't have the right arguments for the trait bound
1208
- can_suggest = CanSuggest :: No ;
1209
- } else if let CanSuggest :: Maybe = can_suggest {
1210
- // The closure has the right arguments
1211
- can_suggest = CanSuggest :: Yes ;
1212
- }
1213
- }
1214
- ty:: ClauseKind :: Projection ( proj)
1215
- if self . infcx . can_eq ( self . param_env , proj. projection_ty . self_ty ( ) , * input)
1216
- && tcx. lang_items ( ) . fn_once_output ( ) == Some ( proj. projection_ty . def_id ) =>
1217
- {
1218
- // Verify that `<[closure@...] as FnOnce>::Output` matches the expected
1219
- // `Output` from the trait bound on the function called with the `[closure@...]`
1220
- // as argument.
1221
- let proj = proj. with_self_ty ( tcx, closure_ty) ;
1222
- let o = Obligation :: new ( tcx, cause. clone ( ) , self . param_env , proj) ;
1223
- if !self . infcx . predicate_may_hold ( & o) {
1224
- // Return type doesn't match.
1225
- can_suggest = CanSuggest :: No ;
1226
- } else if let CanSuggest :: Maybe = can_suggest {
1227
- // Return type matches, we can suggest dereferencing the closure's value.
1228
- can_suggest = CanSuggest :: Yes ;
1229
- }
1230
- }
1231
- _ => { }
1158
+ // Get the arguments for the found method, only specifying that `Self` is the receiver type.
1159
+ let args = GenericArgs :: for_item ( tcx, method, |param, _| {
1160
+ if param. index == 0 {
1161
+ possible_rcvr_ty. into ( )
1162
+ } else if param. index == closure_param. index {
1163
+ closure_ty. into ( )
1164
+ } else {
1165
+ self . infcx . var_for_def ( expr. span , param)
1232
1166
}
1233
- }
1234
- if let CanSuggest :: Yes = can_suggest {
1167
+ } ) ;
1168
+
1169
+ let preds = tcx. predicates_of ( method) . instantiate ( tcx, args) ;
1170
+
1171
+ let ocx = ObligationCtxt :: new ( & self . infcx ) ;
1172
+ ocx. register_obligations ( preds. iter ( ) . map ( |( pred, span) | {
1173
+ trace ! ( ?pred) ;
1174
+ Obligation :: misc ( tcx, span, self . mir_def_id ( ) , self . param_env , pred)
1175
+ } ) ) ;
1176
+
1177
+ if ocx. select_all_or_error ( ) . is_empty ( ) {
1235
1178
diag. span_suggestion_verbose (
1236
1179
value. span . shrink_to_lo ( ) ,
1237
1180
"dereference the return value" ,
0 commit comments