@@ -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) ]
@@ -689,15 +692,17 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
689692 |place : Place < ' tcx > , kind, source_info : SourceInfo , live : & DenseBitSet < PlaceIndex > | {
690693 if let Some ( ( index, extra_projections) ) = checked_places. get ( place. as_ref ( ) ) {
691694 if !is_indirect ( extra_projections) {
695+ let is_direct = extra_projections. is_empty ( ) ;
692696 match assignments[ index] . entry ( source_info) {
693697 IndexEntry :: Vacant ( v) => {
694- let access = Access { kind, live : live. contains ( index) } ;
698+ let access = Access { kind, live : live. contains ( index) , is_direct } ;
695699 v. insert ( access) ;
696700 }
697701 IndexEntry :: Occupied ( mut o) => {
698702 // There were already a sighting. Mark this statement as live if it
699703 // was, to avoid false positives.
700704 o. get_mut ( ) . live |= live. contains ( index) ;
705+ o. get_mut ( ) . is_direct &= is_direct;
701706 }
702707 }
703708 }
@@ -781,7 +786,7 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
781786 continue ;
782787 } ;
783788 let source_info = body. local_decls [ place. local ] . source_info ;
784- let access = Access { kind, live : live. contains ( index) } ;
789+ let access = Access { kind, live : live. contains ( index) , is_direct : true } ;
785790 assignments[ index] . insert ( source_info, access) ;
786791 }
787792 }
@@ -1049,26 +1054,28 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> {
10491054
10501055 let Some ( ( name, decl_span) ) = self . checked_places . names [ index] else { continue } ;
10511056
1052- // We have outstanding assignments and with non-trivial drop.
1053- // This is probably a drop-guard, so we do not issue a warning there.
1054- if maybe_drop_guard (
1057+ let is_maybe_drop_guard = maybe_drop_guard (
10551058 tcx,
10561059 self . typing_env ,
10571060 index,
10581061 & self . ever_dropped ,
10591062 self . checked_places ,
10601063 self . body ,
1061- ) {
1062- continue ;
1063- }
1064+ ) ;
10641065
10651066 // We probed MIR in reverse order for dataflow.
10661067 // We revert the vector to give a consistent order to the user.
1067- for ( source_info, Access { live, kind } ) in statements. into_iter ( ) . rev ( ) {
1068+ for ( source_info, Access { live, kind, is_direct } ) in statements. into_iter ( ) . rev ( ) {
10681069 if live {
10691070 continue ;
10701071 }
10711072
1073+ // If this place was dropped and has non-trivial drop,
1074+ // skip reporting field assignments.
1075+ if !is_direct && is_maybe_drop_guard {
1076+ continue ;
1077+ }
1078+
10721079 // Report the dead assignment.
10731080 let Some ( hir_id) = source_info. scope . lint_root ( & self . body . source_scopes ) else {
10741081 continue ;
0 commit comments