@@ -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 }
@@ -1048,26 +1053,28 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
10481053
10491054 let Some ( ( name, decl_span) ) = self . checked_places . names [ index] else { continue } ;
10501055
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 (
1056+ let is_maybe_drop_guard = maybe_drop_guard (
10541057 tcx,
10551058 self . typing_env ,
10561059 index,
10571060 & self . ever_dropped ,
10581061 self . checked_places ,
10591062 self . body ,
1060- ) {
1061- continue ;
1062- }
1063+ ) ;
10631064
10641065 // We probed MIR in reverse order for dataflow.
10651066 // We revert the vector to give a consistent order to the user.
1066- for ( source_info, Access { live, kind } ) in statements. into_iter ( ) . rev ( ) {
1067+ for ( source_info, Access { live, kind, is_direct } ) in statements. into_iter ( ) . rev ( ) {
10671068 if live {
10681069 continue ;
10691070 }
10701071
1072+ // If this place was dropped and has non-trivial drop,
1073+ // skip reporting field assignments.
1074+ if !is_direct && is_maybe_drop_guard {
1075+ continue ;
1076+ }
1077+
10711078 // Report the dead assignment.
10721079 let Some ( hir_id) = source_info. scope . lint_root ( & self . body . source_scopes ) else {
10731080 continue ;
0 commit comments