@@ -20,7 +20,7 @@ use rustc::ty::maps::Providers;
20
20
use rustc:: mir:: { AssertMessage , BasicBlock , BorrowKind , Location , Place } ;
21
21
use rustc:: mir:: { Mir , Mutability , Operand , Projection , ProjectionElem , Rvalue } ;
22
22
use rustc:: mir:: { Field , Statement , StatementKind , Terminator , TerminatorKind } ;
23
- use rustc:: mir:: ClosureRegionRequirements ;
23
+ use rustc:: mir:: { ClosureRegionRequirements , Local } ;
24
24
25
25
use rustc_data_structures:: control_flow_graph:: dominators:: Dominators ;
26
26
use rustc_data_structures:: fx:: FxHashSet ;
@@ -729,6 +729,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
729
729
erased_drop_place_ty : ty:: Ty < ' gcx > ,
730
730
span : Span ,
731
731
) {
732
+ let gcx = self . tcx . global_tcx ( ) ;
733
+ let drop_field = |
734
+ mir : & mut MirBorrowckCtxt < ' cx , ' gcx , ' tcx > ,
735
+ ( index, field) : ( usize , ty:: Ty < ' gcx > ) ,
736
+ | {
737
+ let field_ty = gcx. normalize_erasing_regions( mir. param_env, field) ;
738
+ let place = drop_place. clone( ) . field( Field :: new( index) , field_ty) ;
739
+
740
+ mir. visit_terminator_drop( loc, term, flow_state, & place, field_ty, span) ;
741
+ } ;
742
+
732
743
match erased_drop_place_ty. sty {
733
744
// When a struct is being dropped, we need to check
734
745
// whether it has a destructor, if it does, then we can
@@ -737,22 +748,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
737
748
// destructor but `bar` does not, we will only check for
738
749
// borrows of `x.foo` and not `x.bar`. See #47703.
739
750
ty : : TyAdt ( def, substs) if def. is_struct( ) && !def. has_dtor( self . tcx) => {
740
- for ( index, field) in def. all_fields ( ) . enumerate ( ) {
741
- let gcx = self . tcx . global_tcx ( ) ;
742
- let field_ty = field. ty ( gcx, substs) ;
743
- let field_ty = gcx. normalize_erasing_regions ( self . param_env , field_ty) ;
744
- let place = drop_place. clone ( ) . field ( Field :: new ( index) , field_ty) ;
745
-
746
- self . visit_terminator_drop ( loc, term, flow_state, & place, field_ty, span) ;
747
- }
751
+ def. all_fields( )
752
+ . map( |field| field. ty( gcx, substs) )
753
+ . enumerate( )
754
+ . for_each( |field| drop_field( self , field) ) ;
755
+ }
756
+ // Same as above, but for tuples.
757
+ ty:: TyTuple ( tys) => {
758
+ tys. iter( ) . cloned( ) . enumerate( )
759
+ . for_each( |field| drop_field( self , field) ) ;
760
+ }
761
+ // Closures and generators also have disjoint fields, but they are only
762
+ // directly accessed in the body of the closure/generator.
763
+ ty:: TyClosure ( def, substs)
764
+ | ty:: TyGenerator ( def, substs, ..)
765
+ if * drop_place == Place :: Local ( Local :: new( 1 ) ) && !self . mir. upvar_decls. is_empty( )
766
+ => {
767
+ substs. upvar_tys( def, self . tcx) . enumerate( )
768
+ . for_each( |field| drop_field( self , field) ) ;
748
769
}
749
770
_ => {
750
771
// We have now refined the type of the value being
751
772
// dropped (potentially) to just the type of a
752
773
// subfield; so check whether that field's type still
753
774
// "needs drop". If so, we assume that the destructor
754
775
// may access any data it likes (i.e., a Deep Write).
755
- let gcx = self . tcx . global_tcx ( ) ;
756
776
if erased_drop_place_ty. needs_drop( gcx, self . param_env) {
757
777
self . access_place(
758
778
ContextKind :: Drop . new( loc) ,
0 commit comments