@@ -31,13 +31,15 @@ use ty;
31
31
use ty:: subst:: { Subst , Substs } ;
32
32
use ty:: util:: IntTypeExt ;
33
33
use ty:: walk:: TypeWalker ;
34
- use util:: nodemap:: { NodeSet , DefIdMap , FxHashMap } ;
34
+ use util:: common:: ErrorReported ;
35
+ use util:: nodemap:: { NodeSet , DefIdMap , FxHashMap , FxHashSet } ;
35
36
36
37
use serialize:: { self , Encodable , Encoder } ;
37
38
use std:: cell:: { Cell , RefCell , Ref } ;
38
39
use std:: collections:: BTreeMap ;
39
40
use std:: cmp;
40
41
use std:: hash:: { Hash , Hasher } ;
42
+ use std:: iter:: FromIterator ;
41
43
use std:: ops:: Deref ;
42
44
use std:: rc:: Rc ;
43
45
use std:: slice;
@@ -1332,17 +1334,6 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
1332
1334
pub struct Destructor {
1333
1335
/// The def-id of the destructor method
1334
1336
pub did : DefId ,
1335
- /// Invoking the destructor of a dtorck type during usual cleanup
1336
- /// (e.g. the glue emitted for stack unwinding) requires all
1337
- /// lifetimes in the type-structure of `adt` to strictly outlive
1338
- /// the adt value itself.
1339
- ///
1340
- /// If `adt` is not dtorck, then the adt's destructor can be
1341
- /// invoked even when there are lifetimes in the type-structure of
1342
- /// `adt` that do not strictly outlive the adt value itself.
1343
- /// (This allows programs to make cyclic structures without
1344
- /// resorting to unsafe means; see RFCs 769 and 1238).
1345
- pub is_dtorck : bool ,
1346
1337
}
1347
1338
1348
1339
bitflags ! {
@@ -1609,14 +1600,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
1609
1600
}
1610
1601
}
1611
1602
1612
- /// Returns whether this is a dtorck type. If this returns
1613
- /// true, this type being safe for destruction requires it to be
1614
- /// alive; Otherwise, only the contents are required to be.
1615
- #[ inline]
1616
- pub fn is_dtorck ( & ' gcx self , tcx : TyCtxt ) -> bool {
1617
- self . destructor ( tcx) . map_or ( false , |d| d. is_dtorck )
1618
- }
1619
-
1620
1603
/// Returns whether this type is #[fundamental] for the purposes
1621
1604
/// of coherence checking.
1622
1605
#[ inline]
@@ -1780,33 +1763,26 @@ impl<'a, 'gcx, 'tcx> AdtDef {
1780
1763
queries:: adt_destructor:: get ( tcx, DUMMY_SP , self . did )
1781
1764
}
1782
1765
1783
- /// Returns a simpler type such that `Self: Sized` if and only
1766
+ /// Returns a list of types such that `Self: Sized` if and only
1784
1767
/// if that type is Sized, or `TyErr` if this type is recursive.
1785
1768
///
1786
- /// HACK: instead of returning a list of types, this function can
1787
- /// return a tuple. In that case, the result is Sized only if
1788
- /// all elements of the tuple are Sized.
1789
- ///
1790
- /// This is generally the `struct_tail` if this is a struct, or a
1791
- /// tuple of them if this is an enum.
1792
- ///
1793
1769
/// Oddly enough, checking that the sized-constraint is Sized is
1794
1770
/// actually more expressive than checking all members:
1795
1771
/// the Sized trait is inductive, so an associated type that references
1796
1772
/// Self would prevent its containing ADT from being Sized.
1797
1773
///
1798
1774
/// Due to normalization being eager, this applies even if
1799
1775
/// the associated type is behind a pointer, e.g. issue #31299.
1800
- pub fn sized_constraint ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> Ty < ' tcx > {
1776
+ pub fn sized_constraint ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> & ' tcx [ Ty < ' tcx > ] {
1801
1777
match queries:: adt_sized_constraint:: try_get ( tcx, DUMMY_SP , self . did ) {
1802
- Ok ( ty ) => ty ,
1778
+ Ok ( tys ) => tys ,
1803
1779
Err ( _) => {
1804
1780
debug ! ( "adt_sized_constraint: {:?} is recursive" , self ) ;
1805
1781
// This should be reported as an error by `check_representable`.
1806
1782
//
1807
1783
// Consider the type as Sized in the meanwhile to avoid
1808
1784
// further errors.
1809
- tcx. types . err
1785
+ tcx. intern_type_list ( & [ tcx . types . err ] )
1810
1786
}
1811
1787
}
1812
1788
}
@@ -1836,18 +1812,13 @@ impl<'a, 'gcx, 'tcx> AdtDef {
1836
1812
1837
1813
TyAdt ( adt, substs) => {
1838
1814
// recursive case
1839
- let adt_ty =
1840
- adt. sized_constraint ( tcx)
1841
- . subst ( tcx, substs) ;
1815
+ let adt_tys = adt. sized_constraint ( tcx) ;
1842
1816
debug ! ( "sized_constraint_for_ty({:?}) intermediate = {:?}" ,
1843
- ty, adt_ty) ;
1844
- if let ty:: TyTuple ( ref tys, _) = adt_ty. sty {
1845
- tys. iter ( ) . flat_map ( |ty| {
1846
- self . sized_constraint_for_ty ( tcx, ty)
1847
- } ) . collect ( )
1848
- } else {
1849
- self . sized_constraint_for_ty ( tcx, adt_ty)
1850
- }
1817
+ ty, adt_tys) ;
1818
+ adt_tys. iter ( )
1819
+ . map ( |ty| ty. subst ( tcx, substs) )
1820
+ . flat_map ( |ty| self . sized_constraint_for_ty ( tcx, ty) )
1821
+ . collect ( )
1851
1822
}
1852
1823
1853
1824
TyProjection ( ..) | TyAnon ( ..) => {
@@ -2697,13 +2668,7 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
2697
2668
2698
2669
/// Calculates the Sized-constraint.
2699
2670
///
2700
- /// As the Sized-constraint of enums can be a *set* of types,
2701
- /// the Sized-constraint may need to be a set also. Because introducing
2702
- /// a new type of IVar is currently a complex affair, the Sized-constraint
2703
- /// may be a tuple.
2704
- ///
2705
- /// In fact, there are only a few options for the constraint:
2706
- /// - `bool`, if the type is always Sized
2671
+ /// In fact, there are only a few options for the types in the constraint:
2707
2672
/// - an obviously-unsized type
2708
2673
/// - a type parameter or projection whose Sizedness can't be known
2709
2674
/// - a tuple of type parameters or projections, if there are multiple
@@ -2712,26 +2677,50 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
2712
2677
/// check should catch this case.
2713
2678
fn adt_sized_constraint < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
2714
2679
def_id : DefId )
2715
- -> Ty < ' tcx > {
2680
+ -> & ' tcx [ Ty < ' tcx > ] {
2716
2681
let def = tcx. lookup_adt_def ( def_id) ;
2717
2682
2718
- let tys : Vec < _ > = def. variants . iter ( ) . flat_map ( |v| {
2683
+ let result = tcx . intern_type_list ( & def. variants . iter ( ) . flat_map ( |v| {
2719
2684
v. fields . last ( )
2720
2685
} ) . flat_map ( |f| {
2721
- let ty = tcx. item_type ( f. did ) ;
2722
- def. sized_constraint_for_ty ( tcx, ty)
2723
- } ) . collect ( ) ;
2724
-
2725
- let ty = match tys. len ( ) {
2726
- _ if tys. references_error ( ) => tcx. types . err ,
2727
- 0 => tcx. types . bool ,
2728
- 1 => tys[ 0 ] ,
2729
- _ => tcx. intern_tup ( & tys[ ..] , false )
2730
- } ;
2686
+ def. sized_constraint_for_ty ( tcx, tcx. item_type ( f. did ) )
2687
+ } ) . collect :: < Vec < _ > > ( ) ) ;
2731
2688
2732
- debug ! ( "adt_sized_constraint: {:?} => {:?}" , def, ty ) ;
2689
+ debug ! ( "adt_sized_constraint: {:?} => {:?}" , def, result ) ;
2733
2690
2734
- ty
2691
+ result
2692
+ }
2693
+
2694
+ /// Calculates the dtorck constraint for a type.
2695
+ fn adt_dtorck_constraint < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
2696
+ def_id : DefId )
2697
+ -> DtorckConstraint < ' tcx > {
2698
+ let def = tcx. lookup_adt_def ( def_id) ;
2699
+ let span = tcx. def_span ( def_id) ;
2700
+ debug ! ( "dtorck_constraint: {:?}" , def) ;
2701
+
2702
+ if def. is_phantom_data ( ) {
2703
+ let result = DtorckConstraint {
2704
+ outlives : vec ! [ ] ,
2705
+ dtorck_types : vec ! [
2706
+ tcx. mk_param_from_def( & tcx. item_generics( def_id) . types[ 0 ] )
2707
+ ]
2708
+ } ;
2709
+ debug ! ( "dtorck_constraint: {:?} => {:?}" , def, result) ;
2710
+ return result;
2711
+ }
2712
+
2713
+ let mut result = def. all_fields ( )
2714
+ . map ( |field| tcx. item_type ( field. did ) )
2715
+ . map ( |fty| tcx. dtorck_constraint_for_ty ( span, fty, 0 , fty) )
2716
+ . collect :: < Result < DtorckConstraint , ErrorReported > > ( )
2717
+ . unwrap_or ( DtorckConstraint :: empty ( ) ) ;
2718
+ result. outlives . extend ( tcx. destructor_constraints ( def) ) ;
2719
+ result. dedup ( ) ;
2720
+
2721
+ debug ! ( "dtorck_constraint: {:?} => {:?}" , def, result) ;
2722
+
2723
+ result
2735
2724
}
2736
2725
2737
2726
fn associated_item_def_ids < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
@@ -2762,13 +2751,15 @@ pub fn provide(providers: &mut ty::maps::Providers) {
2762
2751
associated_item,
2763
2752
associated_item_def_ids,
2764
2753
adt_sized_constraint,
2754
+ adt_dtorck_constraint,
2765
2755
..* providers
2766
2756
} ;
2767
2757
}
2768
2758
2769
2759
pub fn provide_extern ( providers : & mut ty:: maps:: Providers ) {
2770
2760
* providers = ty:: maps:: Providers {
2771
2761
adt_sized_constraint,
2762
+ adt_dtorck_constraint,
2772
2763
..* providers
2773
2764
} ;
2774
2765
}
@@ -2784,3 +2775,46 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) {
2784
2775
pub struct CrateInherentImpls {
2785
2776
pub inherent_impls : DefIdMap < Rc < Vec < DefId > > > ,
2786
2777
}
2778
+
2779
+ /// A set of constraints that need to be satisfied in order for
2780
+ /// a type to be valid for destruction.
2781
+ #[ derive( Clone , Debug ) ]
2782
+ pub struct DtorckConstraint < ' tcx > {
2783
+ /// Types that are required to be alive in order for this
2784
+ /// type to be valid for destruction.
2785
+ pub outlives : Vec < ty:: subst:: Kind < ' tcx > > ,
2786
+ /// Types that could not be resolved: projections and params.
2787
+ pub dtorck_types : Vec < Ty < ' tcx > > ,
2788
+ }
2789
+
2790
+ impl < ' tcx > FromIterator < DtorckConstraint < ' tcx > > for DtorckConstraint < ' tcx >
2791
+ {
2792
+ fn from_iter < I : IntoIterator < Item =DtorckConstraint < ' tcx > > > ( iter : I ) -> Self {
2793
+ let mut result = Self :: empty ( ) ;
2794
+
2795
+ for constraint in iter {
2796
+ result. outlives . extend ( constraint. outlives ) ;
2797
+ result. dtorck_types . extend ( constraint. dtorck_types ) ;
2798
+ }
2799
+
2800
+ result
2801
+ }
2802
+ }
2803
+
2804
+
2805
+ impl < ' tcx > DtorckConstraint < ' tcx > {
2806
+ fn empty ( ) -> DtorckConstraint < ' tcx > {
2807
+ DtorckConstraint {
2808
+ outlives : vec ! [ ] ,
2809
+ dtorck_types : vec ! [ ]
2810
+ }
2811
+ }
2812
+
2813
+ fn dedup < ' a > ( & mut self ) {
2814
+ let mut outlives = FxHashSet ( ) ;
2815
+ let mut dtorck_types = FxHashSet ( ) ;
2816
+
2817
+ self . outlives . retain ( |& val| outlives. replace ( val) . is_none ( ) ) ;
2818
+ self . dtorck_types . retain ( |& val| dtorck_types. replace ( val) . is_none ( ) ) ;
2819
+ }
2820
+ }
0 commit comments