88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use borrow_check:: { WriteKind , StorageDeadOrDrop } ;
11+ use borrow_check:: WriteKind ;
1212use borrow_check:: prefixes:: IsPrefixOf ;
1313use borrow_check:: nll:: explain_borrow:: BorrowExplanation ;
1414use rustc:: middle:: region:: ScopeTree ;
1515use rustc:: mir:: {
1616 self , AggregateKind , BindingForm , BorrowKind , ClearCrossCrate , FakeReadCause , Field , Local ,
17- LocalDecl , LocalKind , Location , Operand , Place , ProjectionElem , Rvalue , Statement ,
18- StatementKind , TerminatorKind , VarBindingForm ,
17+ LocalDecl , LocalKind , Location , Operand , Place , PlaceProjection , ProjectionElem , Rvalue ,
18+ Statement , StatementKind , TerminatorKind , VarBindingForm ,
1919} ;
2020use rustc:: hir;
2121use rustc:: hir:: def_id:: DefId ;
@@ -452,13 +452,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
452452 self . access_place_error_reported
453453 . insert ( ( root_place. clone ( ) , borrow_span) ) ;
454454
455- if let Some ( WriteKind :: StorageDeadOrDrop ( StorageDeadOrDrop :: Destructor ) ) = kind {
455+ if let StorageDeadOrDrop :: Destructor ( dropped_ty)
456+ = self . classify_drop_access_kind ( & borrow. borrowed_place )
457+ {
456458 // If a borrow of path `B` conflicts with drop of `D` (and
457459 // we're not in the uninteresting case where `B` is a
458460 // prefix of `D`), then report this as a more interesting
459461 // destructor conflict.
460462 if !borrow. borrowed_place . is_prefix_of ( place_span. 0 ) {
461- self . report_borrow_conflicts_with_destructor ( context, borrow, place_span, kind) ;
463+ self . report_borrow_conflicts_with_destructor (
464+ context,
465+ borrow,
466+ place_span,
467+ kind,
468+ dropped_ty,
469+ ) ;
462470 return ;
463471 }
464472 }
@@ -566,6 +574,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
566574 borrow : & BorrowData < ' tcx > ,
567575 ( place, drop_span) : ( & Place < ' tcx > , Span ) ,
568576 kind : Option < WriteKind > ,
577+ dropped_ty : ty:: Ty < ' tcx > ,
569578 ) {
570579 debug ! (
571580 "report_borrow_conflicts_with_destructor(\
@@ -579,28 +588,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
579588
580589 let mut err = self . infcx . tcx . cannot_borrow_across_destructor ( borrow_span, Origin :: Mir ) ;
581590
582- let ( what_was_dropped, dropped_ty) = {
583- let desc = match self . describe_place ( place) {
584- Some ( name) => format ! ( "`{}`" , name. as_str( ) ) ,
585- None => format ! ( "temporary value" ) ,
586- } ;
587- let ty = place. ty ( self . mir , self . infcx . tcx ) . to_ty ( self . infcx . tcx ) ;
588- ( desc, ty)
591+ let what_was_dropped = match self . describe_place ( place) {
592+ Some ( name) => format ! ( "`{}`" , name. as_str( ) ) ,
593+ None => format ! ( "temporary value" ) ,
589594 } ;
590595
591- let label = match dropped_ty. sty {
592- ty:: Adt ( adt, _) if adt. has_dtor ( self . infcx . tcx ) && !adt. is_box ( ) => {
593- match self . describe_place ( & borrow. borrowed_place ) {
594- Some ( borrowed) =>
595- format ! ( "here, drop of {D} needs exclusive access to `{B}`, \
596- because the type `{T}` implements the `Drop` trait",
597- D =what_was_dropped, T =dropped_ty, B =borrowed) ,
598- None =>
599- format ! ( "here is drop of {D}; whose type `{T}` implements the `Drop` trait" ,
600- D =what_was_dropped, T =dropped_ty) ,
601- }
602- }
603- _ => format ! ( "drop of {D} occurs here" , D =what_was_dropped) ,
596+ let label = match self . describe_place ( & borrow. borrowed_place ) {
597+ Some ( borrowed) =>
598+ format ! ( "here, drop of {D} needs exclusive access to `{B}`, \
599+ because the type `{T}` implements the `Drop` trait",
600+ D =what_was_dropped, T =dropped_ty, B =borrowed) ,
601+ None =>
602+ format ! ( "here is drop of {D}; whose type `{T}` implements the `Drop` trait" ,
603+ D =what_was_dropped, T =dropped_ty) ,
604604 } ;
605605 err. span_label ( drop_span, label) ;
606606
@@ -880,6 +880,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
880880
881881pub ( super ) struct IncludingDowncast ( bool ) ;
882882
883+ /// Which case a StorageDeadOrDrop is for.
884+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
885+ enum StorageDeadOrDrop < ' tcx > {
886+ LocalStorageDead ,
887+ BoxedStorageDead ,
888+ Destructor ( ty:: Ty < ' tcx > ) ,
889+ }
890+
883891impl < ' cx , ' gcx , ' tcx > MirBorrowckCtxt < ' cx , ' gcx , ' tcx > {
884892 // End-user visible description of `place` if one can be found. If the
885893 // place is a temporary for instance, None will be returned.
@@ -1167,6 +1175,56 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11671175 }
11681176 }
11691177
1178+ fn classify_drop_access_kind ( & self , place : & Place < ' tcx > ) -> StorageDeadOrDrop < ' tcx > {
1179+ let tcx = self . infcx . tcx ;
1180+ match place {
1181+ Place :: Local ( _)
1182+ | Place :: Static ( _)
1183+ | Place :: Promoted ( _) => StorageDeadOrDrop :: LocalStorageDead ,
1184+ Place :: Projection ( box PlaceProjection { base, elem } ) => {
1185+ let base_access = self . classify_drop_access_kind ( base) ;
1186+ match elem {
1187+ ProjectionElem :: Deref => {
1188+ match base_access {
1189+ StorageDeadOrDrop :: LocalStorageDead
1190+ | StorageDeadOrDrop :: BoxedStorageDead => {
1191+ assert ! ( base. ty( self . mir, tcx) . to_ty( tcx) . is_box( ) ,
1192+ "Drop of value behind a reference or raw pointer" ) ;
1193+ StorageDeadOrDrop :: BoxedStorageDead
1194+ }
1195+ StorageDeadOrDrop :: Destructor ( _) => {
1196+ base_access
1197+ }
1198+ }
1199+ }
1200+ ProjectionElem :: Field ( ..)
1201+ | ProjectionElem :: Downcast ( ..) => {
1202+ let base_ty = base. ty ( self . mir , tcx) . to_ty ( tcx) ;
1203+ match base_ty. sty {
1204+ ty:: Adt ( def, _) if def. has_dtor ( tcx) => {
1205+ // Report the outermost adt with a destructor
1206+ match base_access {
1207+ StorageDeadOrDrop :: Destructor ( _) => {
1208+ base_access
1209+ }
1210+ StorageDeadOrDrop :: LocalStorageDead
1211+ | StorageDeadOrDrop :: BoxedStorageDead => {
1212+ StorageDeadOrDrop :: Destructor ( base_ty)
1213+ }
1214+ }
1215+ }
1216+ _ => base_access,
1217+ }
1218+ }
1219+
1220+ ProjectionElem :: ConstantIndex { .. }
1221+ | ProjectionElem :: Subslice { .. }
1222+ | ProjectionElem :: Index ( _) => base_access,
1223+ }
1224+ }
1225+ }
1226+ }
1227+
11701228 /// Annotate argument and return type of function and closure with (synthesized) lifetime for
11711229 /// borrow of local value that does not live long enough.
11721230 fn annotate_argument_and_return_for_borrow (
0 commit comments