@@ -21,7 +21,7 @@ use ty::fold::TypeVisitor;
21
21
use ty:: layout:: { Layout , LayoutError } ;
22
22
use ty:: TypeVariants :: * ;
23
23
use util:: common:: ErrorReported ;
24
- use util:: nodemap:: FxHashMap ;
24
+ use util:: nodemap:: { FxHashMap , FxHashSet } ;
25
25
use middle:: lang_items;
26
26
27
27
use rustc_const_math:: { ConstInt , ConstIsize , ConstUsize } ;
@@ -699,6 +699,83 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
699
699
result
700
700
}
701
701
702
+ #[ inline]
703
+ pub fn may_drop ( & ' tcx self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ) -> bool {
704
+ if self . flags . get ( ) . intersects ( TypeFlags :: MAY_DROP_CACHED ) {
705
+ return self . flags . get ( ) . intersects ( TypeFlags :: MAY_DROP ) ;
706
+ }
707
+
708
+ self . may_drop_inner ( tcx, & mut FxHashSet ( ) )
709
+ }
710
+
711
+ fn may_drop_inner ( & ' tcx self ,
712
+ tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
713
+ visited : & mut FxHashSet < Ty < ' tcx > > )
714
+ -> bool {
715
+ if self . flags . get ( ) . intersects ( TypeFlags :: MAY_DROP_CACHED ) {
716
+ return self . flags . get ( ) . intersects ( TypeFlags :: MAY_DROP ) ;
717
+ }
718
+
719
+ // This should be reported as an error by `check_representable`.
720
+ //
721
+ // Consider the type as not needing drop in the meanwhile to avoid
722
+ // further errors.
723
+ if visited. replace ( self ) . is_some ( ) {
724
+ return false ;
725
+ }
726
+
727
+ assert ! ( !self . needs_infer( ) ) ;
728
+
729
+ let result = match self . sty {
730
+ // Fast-path for primitive types
731
+ ty:: TyInfer ( ty:: FreshIntTy ( _) ) | ty:: TyInfer ( ty:: FreshFloatTy ( _) ) |
732
+ ty:: TyBool | ty:: TyInt ( _) | ty:: TyUint ( _) | ty:: TyFloat ( _) | ty:: TyNever |
733
+ ty:: TyFnDef ( ..) | ty:: TyFnPtr ( _) | ty:: TyChar |
734
+ ty:: TyRawPtr ( _) | ty:: TyRef ( ..) | ty:: TyStr => false ,
735
+
736
+ // User destructors are the only way to have concrete drop types.
737
+ ty:: TyAdt ( def, _) if def. has_dtor ( tcx) => true ,
738
+
739
+ // Can refer to a type which may drop.
740
+ // FIXME(eddyb) check this against a ParameterEnvironment.
741
+ ty:: TyDynamic ( ..) | ty:: TyProjection ( ..) | ty:: TyParam ( _) |
742
+ ty:: TyAnon ( ..) | ty:: TyInfer ( _) | ty:: TyError => true ,
743
+
744
+ // Structural recursion.
745
+ ty:: TyArray ( ty, _) | ty:: TySlice ( ty) => {
746
+ ty. may_drop_inner ( tcx, visited)
747
+ }
748
+
749
+ ty:: TyClosure ( def_id, ref substs) => {
750
+ substs. upvar_tys ( def_id, tcx)
751
+ . any ( |ty| ty. may_drop_inner ( tcx, visited) )
752
+ }
753
+
754
+ ty:: TyTuple ( ref tys, _) => {
755
+ tys. iter ( ) . any ( |ty| ty. may_drop_inner ( tcx, visited) )
756
+ }
757
+
758
+ // unions don't have destructors regardless of the child types
759
+ ty:: TyAdt ( def, _) if def. is_union ( ) => false ,
760
+
761
+ ty:: TyAdt ( def, substs) => {
762
+ def. variants . iter ( ) . any ( |v| {
763
+ v. fields . iter ( ) . any ( |f| {
764
+ f. ty ( tcx, substs) . may_drop_inner ( tcx, visited)
765
+ } )
766
+ } )
767
+ }
768
+ } ;
769
+
770
+ self . flags . set ( self . flags . get ( ) | if result {
771
+ TypeFlags :: MAY_DROP_CACHED | TypeFlags :: MAY_DROP
772
+ } else {
773
+ TypeFlags :: MAY_DROP_CACHED
774
+ } ) ;
775
+
776
+ result
777
+ }
778
+
702
779
#[ inline]
703
780
pub fn layout < ' lcx > ( & ' tcx self , infcx : & InferCtxt < ' a , ' tcx , ' lcx > )
704
781
-> Result < & ' tcx Layout , LayoutError < ' tcx > > {
0 commit comments