@@ -463,13 +463,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
463
463
target : _,
464
464
unwind : _,
465
465
} => {
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) ;
473
467
}
474
468
TerminatorKind :: DropAndReplace {
475
469
location : ref drop_place,
@@ -717,6 +711,65 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
717
711
self . tcx . sess . opts . debugging_opts . two_phase_beyond_autoref )
718
712
}
719
713
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
+
720
773
/// Checks an access to the given place to see if it is allowed. Examines the set of borrows
721
774
/// that are in scope, as well as which paths have been initialized, to ensure that (a) the
722
775
/// 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> {
2073
2126
/// currently in, when such distinction matters.
2074
2127
fn each_borrow_involving_path < F > (
2075
2128
& mut self ,
2076
- context : Context ,
2129
+ _context : Context ,
2077
2130
access_place : ( ShallowOrDeep , & Place < ' tcx > ) ,
2078
2131
flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
2079
2132
mut op : F ,
@@ -2085,50 +2138,20 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
2085
2138
// FIXME: analogous code in check_loans first maps `place` to
2086
2139
// its base_path.
2087
2140
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
-
2116
2141
let data = flow_state. borrows . operator ( ) . borrows ( ) ;
2117
2142
2118
2143
// check for loan restricting path P being used. Accounts for
2119
2144
// 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 ;
2132
2155
}
2133
2156
}
2134
2157
}
0 commit comments