1
1
use clippy_utils:: diagnostics:: { span_lint_and_sugg, span_lint_hir_and_then} ;
2
+ use clippy_utils:: mir:: { dropped_without_further_use, enclosing_mir, expr_local, local_assignments} ;
2
3
use clippy_utils:: source:: { snippet_with_applicability, snippet_with_context} ;
3
4
use clippy_utils:: sugg:: has_enclosing_paren;
4
5
use clippy_utils:: ty:: { expr_sig, is_copy, peel_mid_ty_refs, ty_sig, variant_of_res} ;
@@ -15,6 +16,7 @@ use rustc_hir::{
15
16
use rustc_index:: bit_set:: BitSet ;
16
17
use rustc_infer:: infer:: TyCtxtInferExt ;
17
18
use rustc_lint:: { LateContext , LateLintPass } ;
19
+ use rustc_middle:: mir:: { Rvalue , StatementKind } ;
18
20
use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow , AutoBorrowMutability } ;
19
21
use rustc_middle:: ty:: {
20
22
self , subst:: Subst , Binder , BoundVariableKind , EarlyBinder , FnSig , GenericArgKind , List , ParamTy , PredicateKind ,
@@ -1061,10 +1063,10 @@ fn needless_borrow_impl_arg_position<'tcx>(
1061
1063
// elements are modified each time `check_referent` is called.
1062
1064
let mut substs_with_referent_ty = substs_with_expr_ty. to_vec ( ) ;
1063
1065
1064
- let mut check_referent = |referent| {
1066
+ let mut check_reference_and_referent = |reference , referent| {
1065
1067
let referent_ty = cx. typeck_results ( ) . expr_ty ( referent) ;
1066
1068
1067
- if !is_copy ( cx, referent_ty) {
1069
+ if !( is_copy ( cx, referent_ty) || referent_dropped_without_further_use ( cx . tcx , reference ) ) {
1068
1070
return false ;
1069
1071
}
1070
1072
@@ -1106,7 +1108,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
1106
1108
1107
1109
let mut needless_borrow = false ;
1108
1110
while let ExprKind :: AddrOf ( _, _, referent) = expr. kind {
1109
- if !check_referent ( referent) {
1111
+ if !check_reference_and_referent ( expr , referent) {
1110
1112
break ;
1111
1113
}
1112
1114
expr = referent;
@@ -1134,6 +1136,20 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
1134
1136
} )
1135
1137
}
1136
1138
1139
+ fn referent_dropped_without_further_use ( tcx : TyCtxt < ' _ > , reference : & Expr < ' _ > ) -> bool {
1140
+ let mir = enclosing_mir ( tcx, reference. hir_id ) ;
1141
+ if let Some ( local) = expr_local ( tcx, reference)
1142
+ && let [ location] = * local_assignments ( mir, local) . as_slice ( )
1143
+ && let StatementKind :: Assign ( box ( _, Rvalue :: Ref ( _, _, place) ) ) =
1144
+ mir. basic_blocks ( ) [ location. block ] . statements [ location. statement_index ] . kind
1145
+ && !place. has_deref ( )
1146
+ {
1147
+ dropped_without_further_use ( mir, place. local , location) . unwrap_or ( false )
1148
+ } else {
1149
+ false
1150
+ }
1151
+ }
1152
+
1137
1153
// Iteratively replaces `param_ty` with `new_ty` in `substs`, and similarly for each resulting
1138
1154
// projected type that is a type parameter. Returns `false` if replacing the types would have an
1139
1155
// effect on the function signature beyond substituting `new_ty` for `param_ty`.
0 commit comments