@@ -112,7 +112,7 @@ pub struct CrateAnalysis {
112
112
#[ derive( Copy , Clone ) ]
113
113
pub enum DtorKind {
114
114
NoDtor ,
115
- TraitDtor ( DefId , bool )
115
+ TraitDtor ( bool )
116
116
}
117
117
118
118
impl DtorKind {
@@ -126,7 +126,7 @@ impl DtorKind {
126
126
pub fn has_drop_flag ( & self ) -> bool {
127
127
match self {
128
128
& NoDtor => false ,
129
- & TraitDtor ( _ , flag) => flag
129
+ & TraitDtor ( flag) => flag
130
130
}
131
131
}
132
132
}
@@ -797,12 +797,6 @@ pub struct ctxt<'tcx> {
797
797
/// True if the variance has been computed yet; false otherwise.
798
798
pub variance_computed : Cell < bool > ,
799
799
800
- /// A mapping from the def ID of an enum or struct type to the def ID
801
- /// of the method that implements its destructor. If the type is not
802
- /// present in this map, it does not have a destructor. This map is
803
- /// populated during the coherence phase of typechecking.
804
- pub destructor_for_type : RefCell < DefIdMap < DefId > > ,
805
-
806
800
/// A method will be in this list if and only if it is a destructor.
807
801
pub destructors : RefCell < DefIdSet > ,
808
802
@@ -1502,7 +1496,62 @@ pub struct DebruijnIndex {
1502
1496
pub depth : u32 ,
1503
1497
}
1504
1498
1505
- /// Representation of regions:
1499
+ /// Representation of regions.
1500
+ ///
1501
+ /// Unlike types, most region variants are "fictitious", not concrete,
1502
+ /// regions. Among these, `ReStatic`, `ReEmpty` and `ReScope` are the only
1503
+ /// ones representing concrete regions.
1504
+ ///
1505
+ /// ## Bound Regions
1506
+ ///
1507
+ /// These are regions that are stored behind a binder and must be substituted
1508
+ /// with some concrete region before being used. There are 2 kind of
1509
+ /// bound regions: early-bound, which are bound in a TypeScheme/TraitDef,
1510
+ /// and are substituted by a Substs, and late-bound, which are part of
1511
+ /// higher-ranked types (e.g. `for<'a> fn(&'a ())`) and are substituted by
1512
+ /// the likes of `liberate_late_bound_regions`. The distinction exists
1513
+ /// because higher-ranked lifetimes aren't supported in all places. See [1][2].
1514
+ ///
1515
+ /// Unlike TyParam-s, bound regions are not supposed to exist "in the wild"
1516
+ /// outside their binder, e.g. in types passed to type inference, and
1517
+ /// should first be substituted (by skolemized regions, free regions,
1518
+ /// or region variables).
1519
+ ///
1520
+ /// ## Skolemized and Free Regions
1521
+ ///
1522
+ /// One often wants to work with bound regions without knowing their precise
1523
+ /// identity. For example, when checking a function, the lifetime of a borrow
1524
+ /// can end up being assigned to some region parameter. In these cases,
1525
+ /// it must be ensured that bounds on the region can't be accidentally
1526
+ /// assumed without being checked.
1527
+ ///
1528
+ /// The process of doing that is called "skolemization". The bound regions
1529
+ /// are replaced by skolemized markers, which don't satisfy any relation
1530
+ /// not explicity provided.
1531
+ ///
1532
+ /// There are 2 kinds of skolemized regions in rustc: `ReFree` and
1533
+ /// `ReSkolemized`. When checking an item's body, `ReFree` is supposed
1534
+ /// to be used. These also support explicit bounds: both the internally-stored
1535
+ /// *scope*, which the region is assumed to outlive, as well as other
1536
+ /// relations stored in the `FreeRegionMap`. Note that these relations
1537
+ /// aren't checked when you `make_subregion` (or `mk_eqty`), only by
1538
+ /// `resolve_regions_and_report_errors`.
1539
+ ///
1540
+ /// When working with higher-ranked types, some region relations aren't
1541
+ /// yet known, so you can't just call `resolve_regions_and_report_errors`.
1542
+ /// `ReSkolemized` is designed for this purpose. In these contexts,
1543
+ /// there's also the risk that some inference variable laying around will
1544
+ /// get unified with your skolemized region: if you want to check whether
1545
+ /// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a`
1546
+ /// with a skolemized region `'%a`, the variable `'_` would just be
1547
+ /// instantiated to the skolemized region `'%a`, which is wrong because
1548
+ /// the inference variable is supposed to satisfy the relation
1549
+ /// *for every value of the skolemized region*. To ensure that doesn't
1550
+ /// happen, you can use `leak_check`. This is more clearly explained
1551
+ /// by infer/higher_ranked/README.md.
1552
+ ///
1553
+ /// [1] http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/
1554
+ /// [2] http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
1506
1555
#[ derive( Clone , PartialEq , Eq , Hash , Copy ) ]
1507
1556
pub enum Region {
1508
1557
// Region bound in a type or fn declaration which will be
@@ -1532,7 +1581,7 @@ pub enum Region {
1532
1581
1533
1582
/// A skolemized region - basically the higher-ranked version of ReFree.
1534
1583
/// Should not exist after typeck.
1535
- ReSkolemized ( u32 , BoundRegion ) ,
1584
+ ReSkolemized ( SkolemizedRegionVid , BoundRegion ) ,
1536
1585
1537
1586
/// Empty lifetime is for data that is never accessed.
1538
1587
/// Bottom in the region lattice. We treat ReEmpty somewhat
@@ -2168,6 +2217,11 @@ pub struct RegionVid {
2168
2217
pub index : u32
2169
2218
}
2170
2219
2220
+ #[ derive( Clone , Copy , PartialEq , Eq , Hash ) ]
2221
+ pub struct SkolemizedRegionVid {
2222
+ pub index : u32
2223
+ }
2224
+
2171
2225
#[ derive( Clone , Copy , PartialEq , Eq , Hash ) ]
2172
2226
pub enum InferTy {
2173
2227
TyVar ( TyVid ) ,
@@ -2997,7 +3051,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
2997
3051
_ => return Err ( TypeIsStructural ) ,
2998
3052
} ;
2999
3053
3000
- if adt. has_dtor ( tcx ) {
3054
+ if adt. has_dtor ( ) {
3001
3055
return Err ( TypeHasDestructor )
3002
3056
}
3003
3057
@@ -3202,6 +3256,7 @@ bitflags! {
3202
3256
const IS_PHANTOM_DATA = 1 << 3 ,
3203
3257
const IS_SIMD = 1 << 4 ,
3204
3258
const IS_FUNDAMENTAL = 1 << 5 ,
3259
+ const IS_NO_DROP_FLAG = 1 << 6 ,
3205
3260
}
3206
3261
}
3207
3262
@@ -3252,6 +3307,7 @@ pub struct FieldDefData<'tcx, 'container: 'tcx> {
3252
3307
pub struct AdtDefData < ' tcx , ' container : ' tcx > {
3253
3308
pub did : DefId ,
3254
3309
pub variants : Vec < VariantDefData < ' tcx , ' container > > ,
3310
+ destructor : Cell < Option < DefId > > ,
3255
3311
flags : Cell < AdtFlags > ,
3256
3312
}
3257
3313
@@ -3287,6 +3343,9 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
3287
3343
if attr:: contains_name ( & attrs, "fundamental" ) {
3288
3344
flags = flags | AdtFlags :: IS_FUNDAMENTAL ;
3289
3345
}
3346
+ if attr:: contains_name ( & attrs, "unsafe_no_drop_flag" ) {
3347
+ flags = flags | AdtFlags :: IS_NO_DROP_FLAG ;
3348
+ }
3290
3349
if tcx. lookup_simd ( did) {
3291
3350
flags = flags | AdtFlags :: IS_SIMD ;
3292
3351
}
@@ -3300,6 +3359,7 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
3300
3359
did : did,
3301
3360
variants : variants,
3302
3361
flags : Cell :: new ( flags) ,
3362
+ destructor : Cell :: new ( None )
3303
3363
}
3304
3364
}
3305
3365
@@ -3350,8 +3410,11 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
3350
3410
}
3351
3411
3352
3412
/// Returns whether this type has a destructor.
3353
- pub fn has_dtor ( & self , tcx : & ctxt < ' tcx > ) -> bool {
3354
- tcx. destructor_for_type . borrow ( ) . contains_key ( & self . did )
3413
+ pub fn has_dtor ( & self ) -> bool {
3414
+ match self . dtor_kind ( ) {
3415
+ NoDtor => false ,
3416
+ TraitDtor ( ..) => true
3417
+ }
3355
3418
}
3356
3419
3357
3420
/// Asserts this is a struct and returns the struct's unique
@@ -3413,6 +3476,24 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
3413
3476
_ => panic ! ( "unexpected def {:?} in variant_of_def" , def)
3414
3477
}
3415
3478
}
3479
+
3480
+ pub fn destructor ( & self ) -> Option < DefId > {
3481
+ self . destructor . get ( )
3482
+ }
3483
+
3484
+ pub fn set_destructor ( & self , dtor : DefId ) {
3485
+ assert ! ( self . destructor. get( ) . is_none( ) ) ;
3486
+ self . destructor . set ( Some ( dtor) ) ;
3487
+ }
3488
+
3489
+ pub fn dtor_kind ( & self ) -> DtorKind {
3490
+ match self . destructor . get ( ) {
3491
+ Some ( _) => {
3492
+ TraitDtor ( !self . flags . get ( ) . intersects ( AdtFlags :: IS_NO_DROP_FLAG ) )
3493
+ }
3494
+ None => NoDtor ,
3495
+ }
3496
+ }
3416
3497
}
3417
3498
3418
3499
impl < ' tcx , ' container > VariantDefData < ' tcx , ' container > {
@@ -3796,7 +3877,6 @@ impl<'tcx> ctxt<'tcx> {
3796
3877
normalized_cache : RefCell :: new ( FnvHashMap ( ) ) ,
3797
3878
lang_items : lang_items,
3798
3879
provided_method_sources : RefCell :: new ( DefIdMap ( ) ) ,
3799
- destructor_for_type : RefCell :: new ( DefIdMap ( ) ) ,
3800
3880
destructors : RefCell :: new ( DefIdSet ( ) ) ,
3801
3881
inherent_impls : RefCell :: new ( DefIdMap ( ) ) ,
3802
3882
impl_items : RefCell :: new ( DefIdMap ( ) ) ,
@@ -4619,7 +4699,7 @@ impl<'tcx> TyS<'tcx> {
4619
4699
} )
4620
4700
} ) ;
4621
4701
4622
- if def. has_dtor ( cx ) {
4702
+ if def. has_dtor ( ) {
4623
4703
res = res | TC :: OwnsDtor ;
4624
4704
}
4625
4705
@@ -5957,18 +6037,6 @@ impl<'tcx> ctxt<'tcx> {
5957
6037
self . with_path ( id, |path| ast_map:: path_to_string ( path) )
5958
6038
}
5959
6039
5960
- /* If struct_id names a struct with a dtor. */
5961
- pub fn ty_dtor ( & self , struct_id : DefId ) -> DtorKind {
5962
- match self . destructor_for_type . borrow ( ) . get ( & struct_id) {
5963
- Some ( & method_def_id) => {
5964
- let flag = !self . has_attr ( struct_id, "unsafe_no_drop_flag" ) ;
5965
-
5966
- TraitDtor ( method_def_id, flag)
5967
- }
5968
- None => NoDtor ,
5969
- }
5970
- }
5971
-
5972
6040
pub fn with_path < T , F > ( & self , id : DefId , f : F ) -> T where
5973
6041
F : FnOnce ( ast_map:: PathElems ) -> T ,
5974
6042
{
@@ -6053,6 +6121,11 @@ impl<'tcx> ctxt<'tcx> {
6053
6121
self . lookup_adt_def_master ( did)
6054
6122
}
6055
6123
6124
+ /// Return the list of all interned ADT definitions
6125
+ pub fn adt_defs ( & self ) -> Vec < AdtDef < ' tcx > > {
6126
+ self . adt_defs . borrow ( ) . values ( ) . cloned ( ) . collect ( )
6127
+ }
6128
+
6056
6129
/// Given the did of an item, returns its full set of predicates.
6057
6130
pub fn lookup_predicates ( & self , did : DefId ) -> GenericPredicates < ' tcx > {
6058
6131
lookup_locally_or_in_crate_store (
@@ -6700,8 +6773,8 @@ impl<'tcx> ctxt<'tcx> {
6700
6773
/// Returns true if this ADT is a dtorck type, i.e. whether it being
6701
6774
/// safe for destruction requires it to be alive
6702
6775
fn is_adt_dtorck ( & self , adt : AdtDef < ' tcx > ) -> bool {
6703
- let dtor_method = match self . destructor_for_type . borrow ( ) . get ( & adt. did ) {
6704
- Some ( dtor) => * dtor,
6776
+ let dtor_method = match adt. destructor ( ) {
6777
+ Some ( dtor) => dtor,
6705
6778
None => return false
6706
6779
} ;
6707
6780
let impl_did = self . impl_of_method ( dtor_method) . unwrap_or_else ( || {
0 commit comments