@@ -1049,7 +1049,7 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
10491049// If the conditions are met, returns `Some(Position::ImplArg(..))`; otherwise, returns `None`.
10501050// The "is copyable" condition is to avoid the case where removing the `&` means `e` would have to
10511051// be moved, but it cannot be.
1052- #[ expect( clippy:: too_many_arguments) ]
1052+ #[ expect( clippy:: too_many_arguments, clippy :: too_many_lines ) ]
10531053fn needless_borrow_impl_arg_position < ' tcx > (
10541054 cx : & LateContext < ' tcx > ,
10551055 possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
@@ -1092,7 +1092,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
10921092 . iter ( )
10931093 . filter_map ( |predicate| {
10941094 if let PredicateKind :: Trait ( trait_predicate) = predicate. kind ( ) . skip_binder ( )
1095- && trait_predicate. trait_ref . self_ty ( ) == param_ty. to_ty ( cx. tcx )
1095+ && trait_predicate. self_ty ( ) == param_ty. to_ty ( cx. tcx )
10961096 {
10971097 Some ( trait_predicate. trait_ref . def_id )
10981098 } else {
@@ -1111,6 +1111,16 @@ fn needless_borrow_impl_arg_position<'tcx>(
11111111 return Position :: Other ( precedence) ;
11121112 }
11131113
1114+ // See:
1115+ // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1289294201
1116+ // - https://github.com/rust-lang/rust-clippy/pull/9674#issuecomment-1292225232
1117+ if projection_predicates
1118+ . iter ( )
1119+ . any ( |projection_predicate| is_mixed_projection_predicate ( cx, callee_def_id, projection_predicate) )
1120+ {
1121+ return Position :: Other ( precedence) ;
1122+ }
1123+
11141124 // `substs_with_referent_ty` can be constructed outside of `check_referent` because the same
11151125 // elements are modified each time `check_referent` is called.
11161126 let mut substs_with_referent_ty = substs_with_expr_ty. to_vec ( ) ;
@@ -1190,8 +1200,39 @@ fn has_ref_mut_self_method(cx: &LateContext<'_>, trait_def_id: DefId) -> bool {
11901200 } )
11911201}
11921202
1193- fn referent_used_exactly_once < ' tcx > (
1203+ fn is_mixed_projection_predicate < ' tcx > (
11941204 cx : & LateContext < ' tcx > ,
1205+ callee_def_id : DefId ,
1206+ projection_predicate : & ProjectionPredicate < ' tcx > ,
1207+ ) -> bool {
1208+ let generics = cx. tcx . generics_of ( callee_def_id) ;
1209+ // The predicate requires the projected type to equal a type parameter from the parent context.
1210+ if let Some ( term_ty) = projection_predicate. term . ty ( )
1211+ && let ty:: Param ( term_param_ty) = term_ty. kind ( )
1212+ && ( term_param_ty. index as usize ) < generics. parent_count
1213+ {
1214+ // The inner-most self type is a type parameter from the current function.
1215+ let mut projection_ty = projection_predicate. projection_ty ;
1216+ loop {
1217+ match projection_ty. self_ty ( ) . kind ( ) {
1218+ ty:: Projection ( inner_projection_ty) => {
1219+ projection_ty = * inner_projection_ty;
1220+ }
1221+ ty:: Param ( param_ty) => {
1222+ return ( param_ty. index as usize ) >= generics. parent_count ;
1223+ }
1224+ _ => {
1225+ return false ;
1226+ }
1227+ }
1228+ }
1229+ } else {
1230+ false
1231+ }
1232+ }
1233+
1234+ fn referent_used_exactly_once < ' a , ' tcx > (
1235+ cx : & ' a LateContext < ' tcx > ,
11951236 possible_borrowers : & mut Vec < ( LocalDefId , PossibleBorrowerMap < ' tcx , ' tcx > ) > ,
11961237 reference : & Expr < ' tcx > ,
11971238) -> bool {
0 commit comments