@@ -31,13 +31,15 @@ use ty;
3131use ty:: subst:: { Subst , Substs } ;
3232use ty:: util:: IntTypeExt ;
3333use ty:: walk:: TypeWalker ;
34- use util:: nodemap:: { NodeSet , DefIdMap , FxHashMap } ;
34+ use util:: common:: ErrorReported ;
35+ use util:: nodemap:: { NodeSet , DefIdMap , FxHashMap , FxHashSet } ;
3536
3637use serialize:: { self , Encodable , Encoder } ;
3738use std:: cell:: { Cell , RefCell , Ref } ;
3839use std:: collections:: BTreeMap ;
3940use std:: cmp;
4041use std:: hash:: { Hash , Hasher } ;
42+ use std:: iter:: FromIterator ;
4143use std:: ops:: Deref ;
4244use std:: rc:: Rc ;
4345use std:: slice;
@@ -1332,17 +1334,6 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
13321334pub struct Destructor {
13331335 /// The def-id of the destructor method
13341336 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 ,
13461337}
13471338
13481339bitflags ! {
@@ -1609,14 +1600,6 @@ impl<'a, 'gcx, 'tcx> AdtDef {
16091600 }
16101601 }
16111602
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-
16201603 /// Returns whether this type is #[fundamental] for the purposes
16211604 /// of coherence checking.
16221605 #[ inline]
@@ -1780,33 +1763,26 @@ impl<'a, 'gcx, 'tcx> AdtDef {
17801763 queries:: adt_destructor:: get ( tcx, DUMMY_SP , self . did )
17811764 }
17821765
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
17841767 /// if that type is Sized, or `TyErr` if this type is recursive.
17851768 ///
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- ///
17931769 /// Oddly enough, checking that the sized-constraint is Sized is
17941770 /// actually more expressive than checking all members:
17951771 /// the Sized trait is inductive, so an associated type that references
17961772 /// Self would prevent its containing ADT from being Sized.
17971773 ///
17981774 /// Due to normalization being eager, this applies even if
17991775 /// 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 > ] {
18011777 match queries:: adt_sized_constraint:: try_get ( tcx, DUMMY_SP , self . did ) {
1802- Ok ( ty ) => ty ,
1778+ Ok ( tys ) => tys ,
18031779 Err ( _) => {
18041780 debug ! ( "adt_sized_constraint: {:?} is recursive" , self ) ;
18051781 // This should be reported as an error by `check_representable`.
18061782 //
18071783 // Consider the type as Sized in the meanwhile to avoid
18081784 // further errors.
1809- tcx. types . err
1785+ tcx. intern_type_list ( & [ tcx . types . err ] )
18101786 }
18111787 }
18121788 }
@@ -1836,18 +1812,13 @@ impl<'a, 'gcx, 'tcx> AdtDef {
18361812
18371813 TyAdt ( adt, substs) => {
18381814 // recursive case
1839- let adt_ty =
1840- adt. sized_constraint ( tcx)
1841- . subst ( tcx, substs) ;
1815+ let adt_tys = adt. sized_constraint ( tcx) ;
18421816 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 ( )
18511822 }
18521823
18531824 TyProjection ( ..) | TyAnon ( ..) => {
@@ -2697,13 +2668,7 @@ fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
26972668
26982669/// Calculates the Sized-constraint.
26992670///
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:
27072672/// - an obviously-unsized type
27082673/// - a type parameter or projection whose Sizedness can't be known
27092674/// - 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)
27122677/// check should catch this case.
27132678fn adt_sized_constraint < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
27142679 def_id : DefId )
2715- -> Ty < ' tcx > {
2680+ -> & ' tcx [ Ty < ' tcx > ] {
27162681 let def = tcx. lookup_adt_def ( def_id) ;
27172682
2718- let tys : Vec < _ > = def. variants . iter ( ) . flat_map ( |v| {
2683+ let result = tcx . intern_type_list ( & def. variants . iter ( ) . flat_map ( |v| {
27192684 v. fields . last ( )
27202685 } ) . 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 < _ > > ( ) ) ;
27312688
2732- debug ! ( "adt_sized_constraint: {:?} => {:?}" , def, ty ) ;
2689+ debug ! ( "adt_sized_constraint: {:?} => {:?}" , def, result ) ;
27332690
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
27352724}
27362725
27372726fn associated_item_def_ids < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
@@ -2762,13 +2751,15 @@ pub fn provide(providers: &mut ty::maps::Providers) {
27622751 associated_item,
27632752 associated_item_def_ids,
27642753 adt_sized_constraint,
2754+ adt_dtorck_constraint,
27652755 ..* providers
27662756 } ;
27672757}
27682758
27692759pub fn provide_extern ( providers : & mut ty:: maps:: Providers ) {
27702760 * providers = ty:: maps:: Providers {
27712761 adt_sized_constraint,
2762+ adt_dtorck_constraint,
27722763 ..* providers
27732764 } ;
27742765}
@@ -2784,3 +2775,46 @@ pub fn provide_extern(providers: &mut ty::maps::Providers) {
27842775pub struct CrateInherentImpls {
27852776 pub inherent_impls : DefIdMap < Rc < Vec < DefId > > > ,
27862777}
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