@@ -402,16 +402,27 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
402
402
// unbounded type parameter `T`, we must resume the recursive
403
403
// analysis on `T` (since it would be ignored by
404
404
// type_must_outlive).
405
- if has_dtor_of_interest ( tcx, ty) {
406
- debug ! ( "iterate_over_potentially_unsafe_regions_in_type \
407
- {}ty: {} - is a dtorck type!",
408
- ( 0 ..depth) . map( |_| ' ' ) . collect:: <String >( ) ,
409
- ty) ;
410
-
411
- cx. rcx . type_must_outlive ( infer:: SubregionOrigin :: SafeDestructor ( cx. span ) ,
412
- ty, tcx. mk_region ( ty:: ReScope ( cx. parent_scope ) ) ) ;
413
-
414
- return Ok ( ( ) ) ;
405
+ let dropck_kind = has_dtor_of_interest ( tcx, ty) ;
406
+ debug ! ( "iterate_over_potentially_unsafe_regions_in_type \
407
+ ty: {:?} dropck_kind: {:?}", ty, dropck_kind) ;
408
+ match dropck_kind {
409
+ DropckKind :: NoBorrowedDataAccessedInMyDtor => {
410
+ // The maximally blind attribute.
411
+ }
412
+ DropckKind :: BorrowedDataMustStrictlyOutliveSelf => {
413
+ cx. rcx . type_must_outlive ( infer:: SubregionOrigin :: SafeDestructor ( cx. span ) ,
414
+ ty, tcx. mk_region ( ty:: ReScope ( cx. parent_scope ) ) ) ;
415
+ return Ok ( ( ) ) ;
416
+ }
417
+ DropckKind :: RevisedSelf ( revised_ty) => {
418
+ cx. rcx . type_must_outlive ( infer:: SubregionOrigin :: SafeDestructor ( cx. span ) ,
419
+ revised_ty, tcx. mk_region ( ty:: ReScope ( cx. parent_scope ) ) ) ;
420
+ // Do not return early from this case; we want
421
+ // to recursively process the internal structure of Self
422
+ // (because even though the Drop for Self has been asserted
423
+ // safe, the types instantiated for the generics of Self
424
+ // may themselves carry dropck constraints.)
425
+ }
415
426
}
416
427
417
428
debug ! ( "iterate_over_potentially_unsafe_regions_in_type \
@@ -492,16 +503,81 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
492
503
}
493
504
}
494
505
506
+ #[ derive( Copy , Clone , PartialEq , Eq , Debug ) ]
507
+ enum DropckKind < ' tcx > {
508
+ /// The "safe" kind; i.e. conservatively assume any borrow
509
+ /// accessed by dtor, and therefore such data must strictly
510
+ /// outlive self.
511
+ ///
512
+ /// Equivalent to RevisedTy with no change to the self type.
513
+ ///
514
+ /// FIXME: this name may not be general enough; it should be
515
+ /// talking about Phantom lifetimes rather than just borrows.
516
+ ///
517
+ /// (actually, pnkfelix is not 100% sure that's the right
518
+ /// viewpoint. If I'm holding a phantom lifetime just to
519
+ /// constrain a reference type that occurs solely in *negative*
520
+ /// type positions, then my destructor cannot itself ever actually
521
+ /// access such references, right? And don't we end up essentially
522
+ /// requring people to put a fake borrow inside a PhantomData in
523
+ /// order to make phantom lifetimes work anyway?)
524
+ BorrowedDataMustStrictlyOutliveSelf ,
525
+
526
+ /// The nearly completely-unsafe kind.
527
+ ///
528
+ /// Equivalent to RevisedSelf with *all* parameters remapped to ()
529
+ /// (maybe...?)
530
+ NoBorrowedDataAccessedInMyDtor ,
531
+
532
+ /// Assume all borrowed data access by dtor occurs as if Self has the
533
+ /// type carried by this variant. In practice this means that some
534
+ /// of the type parameters are remapped to `()`, because the developer
535
+ /// has asserted that the destructor will not access their contents.
536
+ RevisedSelf ( Ty < ' tcx > ) ,
537
+ }
538
+
539
+ /// Returns the classification of what kind of check should be applied
540
+ /// to `ty`, which may include a revised type where some of the type
541
+ /// parameters are re-mapped to `()` to reflect the destructor's
542
+ /// "purity" with respect to their actual contents.
495
543
fn has_dtor_of_interest < ' a , ' gcx , ' tcx > ( tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
496
- ty : Ty < ' tcx > ) -> bool {
544
+ ty : Ty < ' tcx > ) -> DropckKind < ' tcx > {
497
545
match ty. sty {
498
- ty:: TyAdt ( def, _) => {
499
- def. is_dtorck ( tcx)
546
+ ty:: TyAdt ( adt_def, substs) => {
547
+ if !adt_def. is_dtorck ( tcx) {
548
+ return DropckKind :: NoBorrowedDataAccessedInMyDtor ;
549
+ }
550
+
551
+ // Find the `impl<..> Drop for _` to inspect any
552
+ // attributes attached to the impl's generics.
553
+ let opt_dtor_method = adt_def. destructor ( ) ;
554
+ let dtor_method = if let Some ( dtor_method) = opt_dtor_method {
555
+ dtor_method
556
+ } else {
557
+ return DropckKind :: BorrowedDataMustStrictlyOutliveSelf ;
558
+ } ;
559
+ let method = tcx. impl_or_trait_item ( dtor_method) ;
560
+ let substs = Substs :: for_item ( tcx,
561
+ method. container ( ) . id ( ) ,
562
+ |def, _| if def. pure_wrt_drop {
563
+ tcx. mk_region ( ty:: ReStatic )
564
+ } else {
565
+ substs. region_for_def ( def)
566
+ } ,
567
+ |def, _| if def. pure_wrt_drop {
568
+ tcx. mk_nil ( )
569
+ } else {
570
+ substs. type_for_def ( def)
571
+ } ) ;
572
+ let revised_ty = tcx. mk_adt ( adt_def, & substs) ;
573
+ return DropckKind :: RevisedSelf ( revised_ty) ;
500
574
}
501
575
ty:: TyTrait ( ..) | ty:: TyProjection ( ..) | ty:: TyAnon ( ..) => {
502
576
debug ! ( "ty: {:?} isn't known, and therefore is a dropck type" , ty) ;
503
- true
577
+ return DropckKind :: BorrowedDataMustStrictlyOutliveSelf ;
504
578
} ,
505
- _ => false
579
+ _ => {
580
+ return DropckKind :: NoBorrowedDataAccessedInMyDtor ;
581
+ }
506
582
}
507
583
}
0 commit comments