@@ -182,15 +182,20 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
182182
183183 let clone_usage = if local == ret_local {
184184 CloneUsage {
185- cloned_used : false ,
185+ cloned_use_loc : None . into ( ) ,
186186 cloned_consume_or_mutate_loc : None ,
187187 clone_consumed_or_mutated : true ,
188188 }
189189 } else {
190190 let clone_usage = visit_clone_usage ( local, ret_local, mir, bb) ;
191- if clone_usage. cloned_used && clone_usage. clone_consumed_or_mutated {
191+ if clone_usage. cloned_use_loc . maybe_used ( ) && clone_usage. clone_consumed_or_mutated {
192192 // cloned value is used, and the clone is modified or moved
193193 continue ;
194+ } else if let MirLocalUsage :: Used ( loc) = clone_usage. cloned_use_loc
195+ && possible_borrower. local_is_alive_at ( ret_local, loc)
196+ {
197+ // cloned value is used, and the clone is alive.
198+ continue ;
194199 } else if let Some ( loc) = clone_usage. cloned_consume_or_mutate_loc
195200 // cloned value is mutated, and the clone is alive.
196201 && possible_borrower. local_is_alive_at ( ret_local, loc)
@@ -227,7 +232,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
227232
228233 span_lint_hir_and_then ( cx, REDUNDANT_CLONE , node, sugg_span, "redundant clone" , |diag| {
229234 diag. span_suggestion ( sugg_span, "remove this" , "" , app) ;
230- if clone_usage. cloned_used {
235+ if clone_usage. cloned_use_loc . maybe_used ( ) {
231236 diag. span_note ( span, "cloned value is neither consumed nor mutated" ) ;
232237 } else {
233238 diag. span_note (
@@ -328,10 +333,33 @@ fn base_local_and_movability<'tcx>(
328333 ( place. local , deref || field || slice)
329334}
330335
331- #[ derive( Default ) ]
336+ #[ derive( Debug , Default ) ]
337+ enum MirLocalUsage {
338+ /// The local maybe used, but we are not sure how.
339+ Unknown ,
340+ /// The local is not used.
341+ #[ default]
342+ Unused ,
343+ /// The local is used at a specific location.
344+ Used ( mir:: Location ) ,
345+ }
346+
347+ impl MirLocalUsage {
348+ fn maybe_used ( & self ) -> bool {
349+ matches ! ( self , MirLocalUsage :: Unknown | MirLocalUsage :: Used ( _) )
350+ }
351+ }
352+
353+ impl From < Option < mir:: Location > > for MirLocalUsage {
354+ fn from ( loc : Option < mir:: Location > ) -> Self {
355+ loc. map_or ( MirLocalUsage :: Unused , MirLocalUsage :: Used )
356+ }
357+ }
358+
359+ #[ derive( Debug , Default ) ]
332360struct CloneUsage {
333- /// Whether the cloned value is used after the clone .
334- cloned_used : bool ,
361+ /// The first location where the cloned value is used, if any .
362+ cloned_use_loc : MirLocalUsage ,
335363 /// The first location where the cloned value is consumed or mutated, if any.
336364 cloned_consume_or_mutate_loc : Option < mir:: Location > ,
337365 /// Whether the clone value is mutated.
@@ -359,7 +387,7 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>,
359387 . map ( |mut vec| ( vec. remove ( 0 ) , vec. remove ( 0 ) ) )
360388 {
361389 CloneUsage {
362- cloned_used : ! cloned_use_locs. is_empty ( ) ,
390+ cloned_use_loc : cloned_use_locs. first ( ) . copied ( ) . into ( ) ,
363391 cloned_consume_or_mutate_loc : cloned_consume_or_mutate_locs. first ( ) . copied ( ) ,
364392 // Consider non-temporary clones consumed.
365393 // TODO: Actually check for mutation of non-temporaries.
@@ -368,7 +396,7 @@ fn visit_clone_usage(cloned: mir::Local, clone: mir::Local, mir: &mir::Body<'_>,
368396 }
369397 } else {
370398 CloneUsage {
371- cloned_used : true ,
399+ cloned_use_loc : MirLocalUsage :: Unknown ,
372400 cloned_consume_or_mutate_loc : None ,
373401 clone_consumed_or_mutated : true ,
374402 }
0 commit comments