@@ -45,6 +45,9 @@ struct Access {
4545 /// When we encounter multiple statements at the same location, we only increase the liveness,
4646 /// in order to avoid false positives.
4747 live : bool ,
48+ /// Is this a direct access to the place itself, no projections, or to a field?
49+ /// This helps distinguish `x = ...` from `x.field = ...`
50+ is_direct : bool ,
4851}
4952
5053#[ tracing:: instrument( level = "debug" , skip( tcx) , ret) ]
@@ -650,15 +653,17 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
650653 |place : Place < ' tcx > , kind, source_info : SourceInfo , live : & DenseBitSet < PlaceIndex > | {
651654 if let Some ( ( index, extra_projections) ) = checked_places. get ( place. as_ref ( ) ) {
652655 if !is_indirect ( extra_projections) {
656+ let is_direct = extra_projections. is_empty ( ) ;
653657 match assignments[ index] . entry ( source_info) {
654658 IndexEntry :: Vacant ( v) => {
655- let access = Access { kind, live : live. contains ( index) } ;
659+ let access = Access { kind, live : live. contains ( index) , is_direct } ;
656660 v. insert ( access) ;
657661 }
658662 IndexEntry :: Occupied ( mut o) => {
659663 // There were already a sighting. Mark this statement as live if it
660664 // was, to avoid false positives.
661665 o. get_mut ( ) . live |= live. contains ( index) ;
666+ o. get_mut ( ) . is_direct &= is_direct;
662667 }
663668 }
664669 }
@@ -742,7 +747,7 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
742747 continue ;
743748 } ;
744749 let source_info = body. local_decls [ place. local ] . source_info ;
745- let access = Access { kind, live : live. contains ( index) } ;
750+ let access = Access { kind, live : live. contains ( index) , is_direct : true } ;
746751 assignments[ index] . insert ( source_info, access) ;
747752 }
748753 }
@@ -976,8 +981,10 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
976981 self . checked_places ,
977982 self . body ,
978983 ) {
979- statements. clear ( ) ;
980- continue ;
984+ statements. retain ( |_, access| access. is_direct ) ;
985+ if statements. is_empty ( ) {
986+ continue ;
987+ }
981988 }
982989
983990 let typo = maybe_suggest_typo ( ) ;
@@ -1048,26 +1055,28 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
10481055
10491056 let Some ( ( name, decl_span) ) = self . checked_places . names [ index] else { continue } ;
10501057
1051- // We have outstanding assignments and with non-trivial drop.
1052- // This is probably a drop-guard, so we do not issue a warning there.
1053- if maybe_drop_guard (
1058+ let is_maybe_drop_guard = maybe_drop_guard (
10541059 tcx,
10551060 self . typing_env ,
10561061 index,
10571062 & self . ever_dropped ,
10581063 self . checked_places ,
10591064 self . body ,
1060- ) {
1061- continue ;
1062- }
1065+ ) ;
10631066
10641067 // We probed MIR in reverse order for dataflow.
10651068 // We revert the vector to give a consistent order to the user.
1066- for ( source_info, Access { live, kind } ) in statements. into_iter ( ) . rev ( ) {
1069+ for ( source_info, Access { live, kind, is_direct } ) in statements. into_iter ( ) . rev ( ) {
10671070 if live {
10681071 continue ;
10691072 }
10701073
1074+ // If this place was dropped and has non-trivial drop,
1075+ // skip reporting field assignments.
1076+ if !is_direct && is_maybe_drop_guard {
1077+ continue ;
1078+ }
1079+
10711080 // Report the dead assignment.
10721081 let Some ( hir_id) = source_info. scope . lint_root ( & self . body . source_scopes ) else {
10731082 continue ;
0 commit comments