@@ -463,13 +463,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
463463 target : _,
464464 unwind : _,
465465 } => {
466- self . access_place (
467- ContextKind :: Drop . new ( loc) ,
468- ( drop_place, span) ,
469- ( Deep , Write ( WriteKind :: StorageDeadOrDrop ) ) ,
470- LocalMutationIsAllowed :: Yes ,
471- flow_state,
472- ) ;
466+ self . visit_terminator_drop ( loc, term, flow_state, drop_place, span) ;
473467 }
474468 TerminatorKind :: DropAndReplace {
475469 location : ref drop_place,
@@ -717,6 +711,65 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
717711 self . tcx . sess . opts . debugging_opts . two_phase_beyond_autoref )
718712 }
719713
714+ fn visit_terminator_drop (
715+ & mut self ,
716+ loc : Location ,
717+ term : & Terminator < ' tcx > ,
718+ flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
719+ drop_place : & Place < ' tcx > ,
720+ span : Span ,
721+ ) {
722+ let ty = drop_place. ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
723+ match ty. sty {
724+ // When a struct is being dropped, we need to check whether it has a
725+ // destructor, if it does, then we can call it, if it does not then we
726+ // need to check the individual fields instead.
727+ // See #47703.
728+ ty:: TyAdt ( def, substs) if def. is_struct ( ) && !def. has_dtor ( self . tcx ) => {
729+ for ( index, field) in def. all_fields ( ) . enumerate ( ) {
730+ let field_ty = field. ty ( self . tcx , substs) ;
731+ let proj = Projection {
732+ base : drop_place. clone ( ) ,
733+ elem : ProjectionElem :: Field ( Field :: new ( index) , field_ty) ,
734+ } ;
735+ let place = Place :: Projection ( Box :: new ( proj) ) ;
736+
737+ match field_ty. sty {
738+ // It may be the case that this issue occurs with a struct within a
739+ // struct, so we recurse to handle that.
740+ ty:: TyAdt ( def, _) if def. is_struct ( ) && !def. has_dtor ( self . tcx ) => {
741+ self . visit_terminator_drop (
742+ loc,
743+ term,
744+ flow_state,
745+ & place,
746+ span,
747+ ) ;
748+ } ,
749+ _ => {
750+ self . access_place (
751+ ContextKind :: Drop . new ( loc) ,
752+ ( & place, span) ,
753+ ( Shallow ( None ) , Write ( WriteKind :: StorageDeadOrDrop ) ) ,
754+ LocalMutationIsAllowed :: Yes ,
755+ flow_state,
756+ ) ;
757+ } ,
758+ }
759+ }
760+ } ,
761+ _ => {
762+ self . access_place (
763+ ContextKind :: Drop . new ( loc) ,
764+ ( drop_place, span) ,
765+ ( Deep , Write ( WriteKind :: StorageDeadOrDrop ) ) ,
766+ LocalMutationIsAllowed :: Yes ,
767+ flow_state,
768+ ) ;
769+ } ,
770+ }
771+ }
772+
720773 /// Checks an access to the given place to see if it is allowed. Examines the set of borrows
721774 /// that are in scope, as well as which paths have been initialized, to ensure that (a) the
722775 /// place is initialized and (b) it is not borrowed in some way that would prevent this
@@ -2073,7 +2126,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
20732126 /// currently in, when such distinction matters.
20742127 fn each_borrow_involving_path < F > (
20752128 & mut self ,
2076- context : Context ,
2129+ _context : Context ,
20772130 access_place : ( ShallowOrDeep , & Place < ' tcx > ) ,
20782131 flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
20792132 mut op : F ,
@@ -2085,50 +2138,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
20852138 // FIXME: analogous code in check_loans first maps `place` to
20862139 // its base_path.
20872140
2088- // When this function is called as a result of an `access_terminator` call attempting
2089- // to drop a struct, if that struct does not have a destructor, then we need to check
2090- // each of the fields in the struct. See #47703.
2091- let ( access, places) = if let ContextKind :: Drop = context. kind {
2092- let ty = place. ty ( self . mir , self . tcx ) . to_ty ( self . tcx ) ;
2093-
2094- match ty. sty {
2095- ty:: TyAdt ( def, substs) if def. is_struct ( ) && !def. has_dtor ( self . tcx ) => {
2096- let mut places = Vec :: new ( ) ;
2097-
2098- for ( index, field) in def. all_fields ( ) . enumerate ( ) {
2099- let proj = Projection {
2100- base : place. clone ( ) ,
2101- elem : ProjectionElem :: Field ( Field :: new ( index) ,
2102- field. ty ( self . tcx , substs) ) ,
2103- } ;
2104-
2105- places. push ( Place :: Projection ( Box :: new ( proj) ) ) ;
2106- }
2107-
2108- ( ShallowOrDeep :: Shallow ( None ) , places)
2109- } ,
2110- _ => ( access, vec ! [ place. clone( ) ] ) ,
2111- }
2112- } else {
2113- ( access, vec ! [ place. clone( ) ] )
2114- } ;
2115-
21162141 let data = flow_state. borrows . operator ( ) . borrows ( ) ;
21172142
21182143 // check for loan restricting path P being used. Accounts for
21192144 // borrows of P, P.a.b, etc.
2120- for place in places {
2121- let mut elems_incoming = flow_state. borrows . elems_incoming ( ) ;
2122- while let Some ( i) = elems_incoming. next ( ) {
2123- let borrowed = & data[ i. borrow_index ( ) ] ;
2124-
2125- if self . places_conflict ( & borrowed. borrowed_place , & place, access) {
2126- debug ! ( "each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}" ,
2127- i, borrowed, place, access) ;
2128- let ctrl = op ( self , i, borrowed) ;
2129- if ctrl == Control :: Break {
2130- return ;
2131- }
2145+ let mut elems_incoming = flow_state. borrows . elems_incoming ( ) ;
2146+ while let Some ( i) = elems_incoming. next ( ) {
2147+ let borrowed = & data[ i. borrow_index ( ) ] ;
2148+
2149+ if self . places_conflict ( & borrowed. borrowed_place , & place, access) {
2150+ debug ! ( "each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}" ,
2151+ i, borrowed, place, access) ;
2152+ let ctrl = op ( self , i, borrowed) ;
2153+ if ctrl == Control :: Break {
2154+ return ;
21322155 }
21332156 }
21342157 }
0 commit comments