@@ -20,7 +20,6 @@ use rustc_infer::infer::{
2020} ;
2121use rustc_middle:: hir:: place:: PlaceBase ;
2222use rustc_middle:: mir:: { ConstraintCategory , ReturnConstraint } ;
23- use rustc_middle:: traits:: ObligationCause ;
2423use rustc_middle:: ty:: GenericArgs ;
2524use rustc_middle:: ty:: TypeVisitor ;
2625use rustc_middle:: ty:: { self , RegionVid , Ty } ;
@@ -29,8 +28,7 @@ use rustc_span::symbol::{kw, Ident};
2928use rustc_span:: Span ;
3029use rustc_trait_selection:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
3130use 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 } ;
3432
3533use crate :: borrowck_errors;
3634use crate :: session_diagnostics:: {
@@ -1140,16 +1138,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
11401138 return ;
11411139 } ;
11421140
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) ;
11531141 // Get the type for the parameter corresponding to the argument the closure with the
11541142 // lifetime error we had.
11551143 let Some ( input) = tcx
@@ -1163,75 +1151,30 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
11631151 return ;
11641152 } ;
11651153
1166- let cause = ObligationCause :: misc ( expr . span , self . mir_def_id ( ) ) ;
1154+ trace ! ( ?input ) ;
11671155
1168- enum CanSuggest {
1169- Yes ,
1170- No ,
1171- Maybe ,
1172- }
1156+ let ty:: Param ( closure_param) = input. kind ( ) else { return } ;
11731157
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)
12321166 }
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 ( ) {
12351178 diag. span_suggestion_verbose (
12361179 value. span . shrink_to_lo ( ) ,
12371180 "dereference the return value" ,
0 commit comments