@@ -17,8 +17,8 @@ use rustc_infer::infer::TyCtxtInferExt;
17
17
use rustc_lint:: { LateContext , LateLintPass } ;
18
18
use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow , AutoBorrowMutability } ;
19
19
use rustc_middle:: ty:: {
20
- self , subst:: Subst , EarlyBinder , FnSig , ParamTy , PredicateKind , ProjectionPredicate , TraitPredicate , Ty , TyCtxt ,
21
- TypeVisitable , TypeckResults ,
20
+ self , subst:: Subst , EarlyBinder , FnSig , ParamTy , PredicateKind , ProjectionPredicate , TraitPredicate , TraitRef , Ty ,
21
+ TyCtxt , TypeVisitable , TypeckResults ,
22
22
} ;
23
23
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
24
24
use rustc_span:: { symbol:: sym, Span , Symbol } ;
@@ -971,18 +971,6 @@ fn needless_borrow_impl_arg_position<'tcx>(
971
971
} ) ;
972
972
973
973
let predicates = cx. tcx . param_env ( callee_def_id) . caller_bounds ( ) ;
974
- let trait_predicates_for_param_ty = predicates
975
- . iter ( )
976
- . filter_map ( |predicate| {
977
- if let PredicateKind :: Trait ( trait_predicate) = predicate. kind ( ) . skip_binder ( )
978
- && trait_predicate. trait_ref . self_ty ( ) == param_ty. to_ty ( cx. tcx )
979
- {
980
- Some ( trait_predicate)
981
- } else {
982
- None
983
- }
984
- } )
985
- . collect :: < Vec < _ > > ( ) ;
986
974
let projection_predicates = predicates
987
975
. iter ( )
988
976
. filter_map ( |predicate| {
@@ -994,18 +982,26 @@ fn needless_borrow_impl_arg_position<'tcx>(
994
982
} )
995
983
. collect :: < Vec < _ > > ( ) ;
996
984
985
+ let mut trait_with_ref_mut_self_method = false ;
986
+
997
987
// If no traits were found, or only the `Sized` or `Any` traits were found, return.
998
- if trait_predicates_for_param_ty. iter ( ) . all ( |trait_predicate| {
999
- let trait_def_id = trait_predicate. def_id ( ) ;
1000
- Some ( trait_def_id) == sized_trait_def_id || cx. tcx . is_diagnostic_item ( sym:: Any , trait_def_id)
988
+ if predicates. iter ( ) . all ( |predicate| {
989
+ if let PredicateKind :: Trait ( TraitPredicate {
990
+ trait_ref : TraitRef {
991
+ def_id : trait_def_id, ..
992
+ } ,
993
+ ..
994
+ } ) = predicate. kind ( ) . skip_binder ( )
995
+ {
996
+ trait_with_ref_mut_self_method |= has_ref_mut_self_method ( cx, trait_def_id) ;
997
+ Some ( trait_def_id) == sized_trait_def_id || cx. tcx . is_diagnostic_item ( sym:: Any , trait_def_id)
998
+ } else {
999
+ true
1000
+ }
1001
1001
} ) {
1002
1002
return Position :: Other ( precedence) ;
1003
1003
}
1004
1004
1005
- let has_ref_mut_self_method = trait_predicates_for_param_ty
1006
- . iter ( )
1007
- . any ( |TraitPredicate { trait_ref, .. } | has_ref_mut_self_method ( cx, trait_ref. def_id ) ) ;
1008
-
1009
1005
// `substs_with_referent_ty` can be constructed outside of `check_referent` because the same
1010
1006
// elements are modified each time `check_referent` is called.
1011
1007
let mut substs_with_referent_ty = substs_with_expr_ty. to_vec ( ) ;
@@ -1018,7 +1014,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
1018
1014
}
1019
1015
1020
1016
// https://github.com/rust-lang/rust-clippy/pull/9136#pullrequestreview-1037379321
1021
- if has_ref_mut_self_method && !matches ! ( referent_ty. kind( ) , ty:: Ref ( _, _, Mutability :: Mut ) ) {
1017
+ if trait_with_ref_mut_self_method && !matches ! ( referent_ty. kind( ) , ty:: Ref ( _, _, Mutability :: Mut ) ) {
1022
1018
return false ;
1023
1019
}
1024
1020
@@ -1087,29 +1083,22 @@ fn replace_types<'tcx>(
1087
1083
substs : & mut [ ty:: GenericArg < ' tcx > ] ,
1088
1084
) -> bool {
1089
1085
let mut replaced = BitSet :: new_empty ( substs. len ( ) ) ;
1090
-
1091
1086
let mut deque = VecDeque :: with_capacity ( substs. len ( ) ) ;
1092
- deque. push_back ( ( param_ty, new_ty) ) ;
1093
1087
1094
- while let Some ( ( param_ty, new_ty) ) = deque. pop_front ( ) {
1095
- let new_generic_arg = ty:: GenericArg :: from ( new_ty) ;
1096
-
1097
- // If `replaced.is_empty()`, then `param_ty` and `new_ty` are those initially passed in.
1098
- if !( substs[ param_ty. index as usize ] == new_generic_arg
1099
- || fn_sig
1100
- . inputs_and_output
1101
- . iter ( )
1102
- . enumerate ( )
1103
- . all ( |( i, ty) | ( replaced. is_empty ( ) && i == arg_index) || !contains_ty ( ty, param_ty. to_ty ( cx. tcx ) ) ) )
1104
- {
1105
- return false ;
1106
- }
1088
+ if fn_sig
1089
+ . inputs_and_output
1090
+ . iter ( )
1091
+ . enumerate ( )
1092
+ . any ( |( i, ty) | i != arg_index && contains_ty ( ty, param_ty. to_ty ( cx. tcx ) ) )
1093
+ {
1094
+ return false ;
1095
+ }
1107
1096
1108
- // The next line should not panic, but panicking seems better than going into an infinite loop.
1109
- assert ! ( replaced. insert( param_ty. index) ) ;
1097
+ substs[ param_ty. index as usize ] = ty:: GenericArg :: from ( new_ty) ;
1110
1098
1111
- substs [ param_ty . index as usize ] = new_generic_arg ;
1099
+ deque . push_back ( ( param_ty , new_ty ) ) ;
1112
1100
1101
+ while let Some ( ( param_ty, new_ty) ) = deque. pop_front ( ) {
1113
1102
for projection_predicate in projection_predicates {
1114
1103
if projection_predicate. projection_ty . self_ty ( ) == param_ty. to_ty ( cx. tcx )
1115
1104
&& let ty:: Term :: Ty ( term_ty) = projection_predicate. term
@@ -1121,6 +1110,27 @@ fn replace_types<'tcx>(
1121
1110
. mk_projection ( assoc_item. def_id , cx. tcx . mk_substs_trait ( new_ty, & [ ] ) ) ;
1122
1111
let projected_ty = cx. tcx . normalize_erasing_regions ( cx. param_env , projection) ;
1123
1112
1113
+ let inserted = replaced. insert ( term_param_ty. index ) ;
1114
+
1115
+ let new_generic_arg = ty:: GenericArg :: from ( projected_ty) ;
1116
+
1117
+ if substs[ term_param_ty. index as usize ] == new_generic_arg {
1118
+ continue ;
1119
+ }
1120
+
1121
+ // The next line provides some protection against infinite loops.
1122
+ assert ! ( inserted) ;
1123
+
1124
+ if fn_sig
1125
+ . inputs_and_output
1126
+ . iter ( )
1127
+ . any ( |ty| contains_ty ( ty, term_param_ty. to_ty ( cx. tcx ) ) )
1128
+ {
1129
+ return false ;
1130
+ }
1131
+
1132
+ substs[ term_param_ty. index as usize ] = new_generic_arg;
1133
+
1124
1134
deque. push_back ( ( * term_param_ty, projected_ty) ) ;
1125
1135
}
1126
1136
}
0 commit comments