@@ -2073,7 +2073,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
2073
2073
/// currently in, when such distinction matters.
2074
2074
fn each_borrow_involving_path < F > (
2075
2075
& mut self ,
2076
- _context : Context ,
2076
+ context : Context ,
2077
2077
access_place : ( ShallowOrDeep , & Place < ' tcx > ) ,
2078
2078
flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
2079
2079
mut op : F ,
@@ -2085,20 +2085,50 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
2085
2085
// FIXME: analogous code in check_loans first maps `place` to
2086
2086
// its base_path.
2087
2087
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
+
2088
2116
let data = flow_state. borrows . operator ( ) . borrows ( ) ;
2089
2117
2090
2118
// check for loan restricting path P being used. Accounts for
2091
2119
// borrows of P, P.a.b, etc.
2092
- let mut elems_incoming = flow_state. borrows . elems_incoming ( ) ;
2093
- while let Some ( i) = elems_incoming. next ( ) {
2094
- let borrowed = & data[ i. borrow_index ( ) ] ;
2095
-
2096
- if self . places_conflict ( & borrowed. borrowed_place , place, access) {
2097
- debug ! ( "each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}" ,
2098
- i, borrowed, place, access) ;
2099
- let ctrl = op ( self , i, borrowed) ;
2100
- if ctrl == Control :: Break {
2101
- return ;
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
+ }
2102
2132
}
2103
2133
}
2104
2134
}
0 commit comments