@@ -2073,7 +2073,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
20732073 /// currently in, when such distinction matters.
20742074 fn each_borrow_involving_path < F > (
20752075 & mut self ,
2076- _context : Context ,
2076+ context : Context ,
20772077 access_place : ( ShallowOrDeep , & Place < ' tcx > ) ,
20782078 flow_state : & Flows < ' cx , ' gcx , ' tcx > ,
20792079 mut op : F ,
@@ -2085,20 +2085,50 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
20852085 // FIXME: analogous code in check_loans first maps `place` to
20862086 // its base_path.
20872087
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+
20882116 let data = flow_state. borrows . operator ( ) . borrows ( ) ;
20892117
20902118 // check for loan restricting path P being used. Accounts for
20912119 // 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+ }
21022132 }
21032133 }
21042134 }
0 commit comments