@@ -20,7 +20,7 @@ use rustc::ty::maps::Providers;
2020use rustc:: mir:: { AssertMessage , BasicBlock , BorrowKind , Location , Place } ;
2121use rustc:: mir:: { Mir , Mutability , Operand , Projection , ProjectionElem , Rvalue } ;
2222use rustc:: mir:: { Field , Statement , StatementKind , Terminator , TerminatorKind } ;
23- use rustc:: mir:: ClosureRegionRequirements ;
23+ use rustc:: mir:: { ClosureRegionRequirements , Local } ;
2424
2525use rustc_data_structures:: control_flow_graph:: dominators:: Dominators ;
2626use rustc_data_structures:: fx:: FxHashSet ;
@@ -729,6 +729,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
729729 erased_drop_place_ty : ty:: Ty < ' gcx > ,
730730 span : Span ,
731731 ) {
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+
732743 match erased_drop_place_ty. sty {
733744 // When a struct is being dropped, we need to check
734745 // whether it has a destructor, if it does, then we can
@@ -737,22 +748,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
737748 // destructor but `bar` does not, we will only check for
738749 // borrows of `x.foo` and not `x.bar`. See #47703.
739750 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) ) ;
748769 }
749770 _ => {
750771 // We have now refined the type of the value being
751772 // dropped (potentially) to just the type of a
752773 // subfield; so check whether that field's type still
753774 // "needs drop". If so, we assume that the destructor
754775 // may access any data it likes (i.e., a Deep Write).
755- let gcx = self . tcx . global_tcx ( ) ;
756776 if erased_drop_place_ty. needs_drop( gcx, self . param_env) {
757777 self . access_place(
758778 ContextKind :: Drop . new( loc) ,
0 commit comments