@@ -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