@@ -26,7 +26,6 @@ use rustc_middle::ty::{self, RegionVid, Ty};
26
26
use rustc_middle:: ty:: { Region , TyCtxt } ;
27
27
use rustc_span:: symbol:: { kw, Ident } ;
28
28
use rustc_span:: Span ;
29
- use rustc_trait_selection:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
30
29
use rustc_trait_selection:: infer:: InferCtxtExt ;
31
30
use rustc_trait_selection:: traits:: { Obligation , ObligationCtxt } ;
32
31
@@ -813,7 +812,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
813
812
self . add_static_impl_trait_suggestion ( & mut diag, * fr, fr_name, * outlived_fr) ;
814
813
self . suggest_adding_lifetime_params ( & mut diag, * fr, * outlived_fr) ;
815
814
self . suggest_move_on_borrowing_closure ( & mut diag) ;
816
- self . suggest_deref_closure_value ( & mut diag) ;
815
+ self . suggest_deref_closure_return ( & mut diag) ;
817
816
818
817
diag
819
818
}
@@ -1048,116 +1047,107 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
1048
1047
/// When encountering a lifetime error caused by the return type of a closure, check the
1049
1048
/// corresponding trait bound and see if dereferencing the closure return value would satisfy
1050
1049
/// them. If so, we produce a structured suggestion.
1051
- fn suggest_deref_closure_value ( & self , diag : & mut Diag < ' _ > ) {
1050
+ fn suggest_deref_closure_return ( & self , diag : & mut Diag < ' _ > ) {
1052
1051
let tcx = self . infcx . tcx ;
1053
- let map = tcx. hir ( ) ;
1054
1052
1055
1053
// Get the closure return value and type.
1056
- let body_id = map. body_owned_by ( self . mir_def_id ( ) ) ;
1057
- let body = & map. body ( body_id) ;
1058
- let value = & body. value . peel_blocks ( ) ;
1059
- let hir:: Node :: Expr ( closure_expr) = tcx. hir_node_by_def_id ( self . mir_def_id ( ) ) else {
1054
+ let closure_def_id = self . mir_def_id ( ) ;
1055
+ let hir:: Node :: Expr (
1056
+ closure_expr @ hir:: Expr {
1057
+ kind : hir:: ExprKind :: Closure ( hir:: Closure { body, .. } ) , ..
1058
+ } ,
1059
+ ) = tcx. hir_node_by_def_id ( closure_def_id)
1060
+ else {
1060
1061
return ;
1061
1062
} ;
1062
- let fn_call_id = tcx. parent_hir_id ( self . mir_hir_id ( ) ) ;
1063
- let hir:: Node :: Expr ( expr) = tcx. hir_node ( fn_call_id) else { return } ;
1064
- let def_id = map. enclosing_body_owner ( fn_call_id) ;
1065
- let tables = tcx. typeck ( def_id) ;
1066
- let Some ( return_value_ty) = tables. node_type_opt ( value. hir_id ) else { return } ;
1067
- let return_value_ty = self . infcx . resolve_vars_if_possible ( return_value_ty) ;
1063
+ let ty:: Closure ( _, args) = * tcx. type_of ( closure_def_id) . instantiate_identity ( ) . kind ( )
1064
+ else {
1065
+ return ;
1066
+ } ;
1067
+ let args = args. as_closure ( ) ;
1068
+
1069
+ // Make sure that the parent expression is a method call.
1070
+ let parent_expr_id = tcx. parent_hir_id ( self . mir_hir_id ( ) ) ;
1071
+ let hir:: Node :: Expr (
1072
+ parent_expr @ hir:: Expr {
1073
+ kind : hir:: ExprKind :: MethodCall ( _, rcvr, call_args, _) , ..
1074
+ } ,
1075
+ ) = tcx. hir_node ( parent_expr_id)
1076
+ else {
1077
+ return ;
1078
+ } ;
1079
+ let typeck_results = tcx. typeck ( self . mir_def_id ( ) ) ;
1068
1080
1069
1081
// We don't use `ty.peel_refs()` to get the number of `*`s needed to get the root type.
1070
- let mut ty = return_value_ty;
1082
+ let liberated_sig = tcx. liberate_late_bound_regions ( closure_def_id. to_def_id ( ) , args. sig ( ) ) ;
1083
+ let mut peeled_ty = liberated_sig. output ( ) ;
1071
1084
let mut count = 0 ;
1072
- while let ty:: Ref ( _, t , _) = ty . kind ( ) {
1073
- ty = * t ;
1085
+ while let ty:: Ref ( _, ref_ty , _) = * peeled_ty . kind ( ) {
1086
+ peeled_ty = ref_ty ;
1074
1087
count += 1 ;
1075
1088
}
1076
- if !self . infcx . type_is_copy_modulo_regions ( self . param_env , ty ) {
1089
+ if !self . infcx . type_is_copy_modulo_regions ( self . param_env , peeled_ty ) {
1077
1090
return ;
1078
1091
}
1079
1092
1080
1093
// Build a new closure where the return type is an owned value, instead of a ref.
1081
- let Some ( ty:: Closure ( did, args) ) =
1082
- tables. node_type_opt ( closure_expr. hir_id ) . as_ref ( ) . map ( |ty| ty. kind ( ) )
1083
- else {
1084
- return ;
1085
- } ;
1086
- let sig = args. as_closure ( ) . sig ( ) ;
1087
1094
let closure_sig_as_fn_ptr_ty = Ty :: new_fn_ptr (
1088
1095
tcx,
1089
- sig. map_bound ( |s| {
1090
- let unsafety = hir:: Unsafety :: Normal ;
1091
- use rustc_target:: spec:: abi;
1092
- tcx. mk_fn_sig (
1093
- [ s. inputs ( ) [ 0 ] ] ,
1094
- s. output ( ) . peel_refs ( ) ,
1095
- s. c_variadic ,
1096
- unsafety,
1097
- abi:: Abi :: Rust ,
1098
- )
1099
- } ) ,
1100
- ) ;
1101
- let parent_args = GenericArgs :: identity_for_item (
1102
- tcx,
1103
- tcx. typeck_root_def_id ( self . mir_def_id ( ) . to_def_id ( ) ) ,
1096
+ ty:: Binder :: dummy ( tcx. mk_fn_sig (
1097
+ liberated_sig. inputs ( ) . iter ( ) . copied ( ) ,
1098
+ peeled_ty,
1099
+ liberated_sig. c_variadic ,
1100
+ hir:: Unsafety :: Normal ,
1101
+ rustc_target:: spec:: abi:: Abi :: Rust ,
1102
+ ) ) ,
1104
1103
) ;
1105
- let closure_kind = args. as_closure ( ) . kind ( ) ;
1106
- let closure_kind_ty = Ty :: from_closure_kind ( tcx, closure_kind) ;
1107
- let tupled_upvars_ty = self . infcx . next_ty_var ( TypeVariableOrigin {
1108
- kind : TypeVariableOriginKind :: ClosureSynthetic ,
1109
- span : closure_expr. span ,
1110
- } ) ;
1111
- let closure_args = ty:: ClosureArgs :: new (
1104
+ let closure_ty = Ty :: new_closure (
1112
1105
tcx,
1113
- ty:: ClosureArgsParts {
1114
- parent_args,
1115
- closure_kind_ty,
1116
- closure_sig_as_fn_ptr_ty,
1117
- tupled_upvars_ty,
1118
- } ,
1106
+ closure_def_id. to_def_id ( ) ,
1107
+ ty:: ClosureArgs :: new (
1108
+ tcx,
1109
+ ty:: ClosureArgsParts {
1110
+ parent_args : args. parent_args ( ) ,
1111
+ closure_kind_ty : args. kind_ty ( ) ,
1112
+ tupled_upvars_ty : args. tupled_upvars_ty ( ) ,
1113
+ closure_sig_as_fn_ptr_ty,
1114
+ } ,
1115
+ )
1116
+ . args ,
1119
1117
) ;
1120
- let closure_ty = Ty :: new_closure ( tcx, * did, closure_args. args ) ;
1121
- let closure_ty = tcx. erase_regions ( closure_ty) ;
1122
-
1123
- let hir:: ExprKind :: MethodCall ( _, rcvr, args, _) = expr. kind else { return } ;
1124
- let Some ( pos) = args
1125
- . iter ( )
1126
- . enumerate ( )
1127
- . find ( |( _, arg) | arg. hir_id == closure_expr. hir_id )
1128
- . map ( |( i, _) | i)
1118
+
1119
+ let Some ( ( closure_arg_pos, _) ) =
1120
+ call_args. iter ( ) . enumerate ( ) . find ( |( _, arg) | arg. hir_id == closure_expr. hir_id )
1129
1121
else {
1130
1122
return ;
1131
1123
} ;
1132
- // The found `Self` type of the method call.
1133
- let Some ( possible_rcvr_ty) = tables. node_type_opt ( rcvr. hir_id ) else { return } ;
1134
- let Some ( method_def_id) = tables. type_dependent_def_id ( expr. hir_id ) else { return } ;
1135
-
1136
1124
// Get the type for the parameter corresponding to the argument the closure with the
1137
1125
// lifetime error we had.
1138
- let Some ( input) = tcx
1126
+ let Some ( method_def_id) = typeck_results. type_dependent_def_id ( parent_expr. hir_id ) else {
1127
+ return ;
1128
+ } ;
1129
+ let Some ( input_arg) = tcx
1139
1130
. fn_sig ( method_def_id)
1140
- . instantiate_identity ( )
1131
+ . skip_binder ( )
1141
1132
. inputs ( )
1142
1133
. skip_binder ( )
1143
1134
// Methods have a `self` arg, so `pos` is actually `+ 1` to match the method call arg.
1144
- . get ( pos + 1 )
1135
+ . get ( closure_arg_pos + 1 )
1145
1136
else {
1146
1137
return ;
1147
1138
} ;
1148
-
1149
- trace ! ( ?input) ;
1150
-
1151
- let ty:: Param ( closure_param) = input. kind ( ) else { return } ;
1139
+ // If this isn't a param, then we can't substitute a new closure.
1140
+ let ty:: Param ( closure_param) = input_arg. kind ( ) else { return } ;
1152
1141
1153
1142
// Get the arguments for the found method, only specifying that `Self` is the receiver type.
1143
+ let Some ( possible_rcvr_ty) = typeck_results. node_type_opt ( rcvr. hir_id ) else { return } ;
1154
1144
let args = GenericArgs :: for_item ( tcx, method_def_id, |param, _| {
1155
1145
if param. index == 0 {
1156
1146
possible_rcvr_ty. into ( )
1157
1147
} else if param. index == closure_param. index {
1158
1148
closure_ty. into ( )
1159
1149
} else {
1160
- self . infcx . var_for_def ( expr . span , param)
1150
+ self . infcx . var_for_def ( parent_expr . span , param)
1161
1151
}
1162
1152
} ) ;
1163
1153
@@ -1171,7 +1161,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
1171
1161
1172
1162
if ocx. select_all_or_error ( ) . is_empty ( ) {
1173
1163
diag. span_suggestion_verbose (
1174
- value. span . shrink_to_lo ( ) ,
1164
+ tcx . hir ( ) . body ( * body ) . value . peel_blocks ( ) . span . shrink_to_lo ( ) ,
1175
1165
"dereference the return value" ,
1176
1166
"*" . repeat ( count) ,
1177
1167
Applicability :: MachineApplicable ,
0 commit comments