8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use borrow_check:: { WriteKind , StorageDeadOrDrop } ;
11
+ use borrow_check:: WriteKind ;
12
12
use borrow_check:: prefixes:: IsPrefixOf ;
13
13
use borrow_check:: nll:: explain_borrow:: BorrowExplanation ;
14
14
use rustc:: middle:: region:: ScopeTree ;
15
15
use rustc:: mir:: {
16
16
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 ,
19
19
} ;
20
20
use rustc:: hir;
21
21
use rustc:: hir:: def_id:: DefId ;
@@ -452,13 +452,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
452
452
self . access_place_error_reported
453
453
. insert ( ( root_place. clone ( ) , borrow_span) ) ;
454
454
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
+ {
456
458
// If a borrow of path `B` conflicts with drop of `D` (and
457
459
// we're not in the uninteresting case where `B` is a
458
460
// prefix of `D`), then report this as a more interesting
459
461
// destructor conflict.
460
462
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
+ ) ;
462
470
return ;
463
471
}
464
472
}
@@ -566,6 +574,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
566
574
borrow : & BorrowData < ' tcx > ,
567
575
( place, drop_span) : ( & Place < ' tcx > , Span ) ,
568
576
kind : Option < WriteKind > ,
577
+ dropped_ty : ty:: Ty < ' tcx > ,
569
578
) {
570
579
debug ! (
571
580
"report_borrow_conflicts_with_destructor(\
@@ -579,28 +588,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
579
588
580
589
let mut err = self . infcx . tcx . cannot_borrow_across_destructor ( borrow_span, Origin :: Mir ) ;
581
590
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" ) ,
589
594
} ;
590
595
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) ,
604
604
} ;
605
605
err. span_label ( drop_span, label) ;
606
606
@@ -880,6 +880,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
880
880
881
881
pub ( super ) struct IncludingDowncast ( bool ) ;
882
882
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
+
883
891
impl < ' cx , ' gcx , ' tcx > MirBorrowckCtxt < ' cx , ' gcx , ' tcx > {
884
892
// End-user visible description of `place` if one can be found. If the
885
893
// place is a temporary for instance, None will be returned.
@@ -1167,6 +1175,56 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
1167
1175
}
1168
1176
}
1169
1177
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
+
1170
1228
/// Annotate argument and return type of function and closure with (synthesized) lifetime for
1171
1229
/// borrow of local value that does not live long enough.
1172
1230
fn annotate_argument_and_return_for_borrow (
0 commit comments