@@ -2,7 +2,9 @@ use super::implicit_clone::is_clone_like;
22use super :: unnecessary_iter_cloned:: { self , is_into_iter} ;
33use clippy_utils:: diagnostics:: span_lint_and_sugg;
44use clippy_utils:: source:: snippet_opt;
5- use clippy_utils:: ty:: { get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs} ;
5+ use clippy_utils:: ty:: {
6+ contains_ty, get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs,
7+ } ;
68use clippy_utils:: { fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item} ;
79use rustc_errors:: Applicability ;
810use rustc_hir:: { def_id:: DefId , BorrowKind , Expr , ExprKind } ;
@@ -114,7 +116,12 @@ fn check_addr_of_expr(
114116 parent. span,
115117 & format!( "unnecessary use of `{}`" , method_name) ,
116118 "use" ,
117- format!( "{:&>width$}{}" , "" , receiver_snippet, width = n_target_refs - n_receiver_refs) ,
119+ format!(
120+ "{:&>width$}{}" ,
121+ "" ,
122+ receiver_snippet,
123+ width = n_target_refs - n_receiver_refs
124+ ) ,
118125 Applicability :: MachineApplicable ,
119126 ) ;
120127 return true ;
@@ -182,20 +189,10 @@ fn check_into_iter_call_arg(cx: &LateContext<'_>, expr: &Expr<'_>, method_name:
182189 if let Some ( item_ty) = get_iterator_item_ty( cx, parent_ty) ;
183190 if let Some ( receiver_snippet) = snippet_opt( cx, receiver. span) ;
184191 then {
185- if unnecessary_iter_cloned:: check_for_loop_iter(
186- cx,
187- parent,
188- method_name,
189- receiver,
190- true ,
191- ) {
192+ if unnecessary_iter_cloned:: check_for_loop_iter( cx, parent, method_name, receiver, true ) {
192193 return true ;
193194 }
194- let cloned_or_copied = if is_copy( cx, item_ty) {
195- "copied"
196- } else {
197- "cloned"
198- } ;
195+ let cloned_or_copied = if is_copy( cx, item_ty) { "copied" } else { "cloned" } ;
199196 // The next suggestion may be incorrect because the removal of the `to_owned`-like
200197 // function could cause the iterator to hold a reference to a resource that is used
201198 // mutably. See https://github.com/rust-lang/rust-clippy/issues/8148.
@@ -243,18 +240,19 @@ fn check_other_call_arg<'tcx>(
243240 if if trait_predicate. def_id( ) == deref_trait_id {
244241 if let [ projection_predicate] = projection_predicates[ ..] {
245242 let normalized_ty =
246- cx. tcx. subst_and_normalize_erasing_regions( call_substs, cx. param_env, projection_predicate. term) ;
243+ cx. tcx
244+ . subst_and_normalize_erasing_regions( call_substs, cx. param_env, projection_predicate. term) ;
247245 implements_trait( cx, receiver_ty, deref_trait_id, & [ ] )
248- && get_associated_type( cx, receiver_ty, deref_trait_id,
249- "Target" ) . map_or( false , |ty| ty:: Term :: Ty ( ty) == normalized_ty)
246+ && get_associated_type( cx, receiver_ty, deref_trait_id, "Target" )
247+ . map_or( false , |ty| ty:: Term :: Ty ( ty) == normalized_ty)
250248 } else {
251249 false
252250 }
253251 } else if trait_predicate. def_id( ) == as_ref_trait_id {
254252 let composed_substs = compose_substs(
255253 cx,
256254 & trait_predicate. trait_ref. substs. iter( ) . skip( 1 ) . collect:: <Vec <_>>( ) [ ..] ,
257- call_substs
255+ call_substs,
258256 ) ;
259257 implements_trait( cx, receiver_ty, as_ref_trait_id, & composed_substs)
260258 } else {
@@ -264,6 +262,12 @@ fn check_other_call_arg<'tcx>(
264262 // `Target = T`.
265263 if n_refs > 0 || is_copy( cx, receiver_ty) || trait_predicate. def_id( ) != deref_trait_id;
266264 let n_refs = max( n_refs, if is_copy( cx, receiver_ty) { 0 } else { 1 } ) ;
265+ // If the trait is `AsRef` and the input type variable `T` occurs in the output type, then
266+ // `T` must not be instantiated with a reference
267+ // (https://github.com/rust-lang/rust-clippy/issues/8507).
268+ if ( n_refs == 0 && !receiver_ty. is_ref( ) )
269+ || trait_predicate. def_id( ) != as_ref_trait_id
270+ || !contains_ty( fn_sig. output( ) , input) ;
267271 if let Some ( receiver_snippet) = snippet_opt( cx, receiver. span) ;
268272 then {
269273 span_lint_and_sugg(
@@ -339,11 +343,7 @@ fn get_input_traits_and_projections<'tcx>(
339343 if let Some ( arg) = substs. iter( ) . next( ) ;
340344 if let GenericArgKind :: Type ( arg_ty) = arg. unpack( ) ;
341345 if arg_ty == input;
342- then {
343- true
344- } else {
345- false
346- }
346+ then { true } else { false }
347347 }
348348 } ;
349349 match predicate. kind ( ) . skip_binder ( ) {
0 commit comments