@@ -74,12 +74,15 @@ use std::cell::{Cell, RefCell, Ref};
74
74
use std:: cmp;
75
75
use std:: fmt;
76
76
use std:: hash:: { Hash , SipHasher , Hasher } ;
77
+ use std:: marker:: PhantomData ;
77
78
use std:: mem;
78
79
use std:: ops;
79
80
use std:: rc:: Rc ;
80
81
use std:: vec:: IntoIter ;
81
82
use collections:: enum_set:: { self , EnumSet , CLike } ;
83
+ use core:: nonzero:: NonZero ;
82
84
use std:: collections:: { HashMap , HashSet } ;
85
+ use rustc_data_structures:: ivar;
83
86
use syntax:: abi;
84
87
use syntax:: ast:: { CrateNum , DefId , ItemImpl , ItemTrait , LOCAL_CRATE } ;
85
88
use syntax:: ast:: { MutImmutable , MutMutable , Name , NamedField , NodeId } ;
@@ -721,7 +724,7 @@ pub struct CtxtArenas<'tcx> {
721
724
722
725
// references
723
726
trait_defs : TypedArena < TraitDef < ' tcx > > ,
724
- adt_defs : TypedArena < ADTDef < ' tcx > > ,
727
+ adt_defs : TypedArena < ADTDef_ < ' tcx , ' tcx > > ,
725
728
}
726
729
727
730
impl < ' tcx > CtxtArenas < ' tcx > {
@@ -1020,9 +1023,10 @@ impl<'tcx> ctxt<'tcx> {
1020
1023
interned
1021
1024
}
1022
1025
1023
- pub fn intern_adt_def ( & self , did : DefId ) -> & ' tcx ADTDef < ' tcx > {
1024
- let def = ADTDef :: new ( self , did) ;
1026
+ pub fn intern_adt_def ( & self , did : DefId , kind : ADTKind ) -> & ' tcx ADTDef_ < ' tcx , ' tcx > {
1027
+ let def = ADTDef_ :: new ( self , did, kind ) ;
1025
1028
let interned = self . arenas . adt_defs . alloc ( def) ;
1029
+ // this will need a transmute when reverse-variance is removed
1026
1030
self . adt_defs . borrow_mut ( ) . insert ( did, interned) ;
1027
1031
interned
1028
1032
}
@@ -1395,6 +1399,61 @@ impl<'tcx> Hash for TyS<'tcx> {
1395
1399
1396
1400
pub type Ty < ' tcx > = & ' tcx TyS < ' tcx > ;
1397
1401
1402
+ /// An IVar that contains a Ty. 'lt is a (reverse-variant) upper bound
1403
+ /// on the lifetime of the IVar. This is required because of variance
1404
+ /// problems: the IVar needs to be variant with respect to 'tcx (so
1405
+ /// it can be referred to from Ty) but can only be modified if its
1406
+ /// lifetime is exactly 'tcx.
1407
+ ///
1408
+ /// Safety invariants:
1409
+ /// (A) self.0, if fulfilled, is a valid Ty<'tcx>
1410
+ /// (B) no aliases to this value with a 'tcx longer than this
1411
+ /// value's 'lt exist
1412
+ ///
1413
+ /// NonZero is used rather than Unique because Unique isn't Copy.
1414
+ pub struct TyIVar < ' tcx , ' lt : ' tcx > ( ivar:: Ivar < NonZero < * const TyS < ' static > > > ,
1415
+ PhantomData < fn ( TyS < ' lt > ) ->TyS < ' tcx > > ) ;
1416
+
1417
+ impl < ' tcx , ' lt > TyIVar < ' tcx , ' lt > {
1418
+ #[ inline]
1419
+ pub fn new ( ) -> Self {
1420
+ // Invariant (A) satisfied because the IVar is unfulfilled
1421
+ // Invariant (B) because 'lt : 'tcx
1422
+ TyIVar ( ivar:: Ivar :: new ( ) , PhantomData )
1423
+ }
1424
+
1425
+ #[ inline]
1426
+ pub fn get ( & self ) -> Option < Ty < ' tcx > > {
1427
+ match self . 0 . get ( ) {
1428
+ None => None ,
1429
+ // valid because of invariant (A)
1430
+ Some ( v) => Some ( unsafe { & * ( * v as * const TyS < ' tcx > ) } )
1431
+ }
1432
+ }
1433
+ #[ inline]
1434
+ pub fn unwrap ( & self ) -> Ty < ' tcx > {
1435
+ self . get ( ) . unwrap ( )
1436
+ }
1437
+
1438
+ pub fn fulfill ( & self , value : Ty < ' lt > ) {
1439
+ // Invariant (A) is fulfilled, because by (B), every alias
1440
+ // of this has a 'tcx longer than 'lt.
1441
+ let value: * const TyS < ' lt > = value;
1442
+ // FIXME(27214): unneeded [as *const ()]
1443
+ let value = value as * const ( ) as * const TyS < ' static > ;
1444
+ self . 0 . fulfill ( unsafe { NonZero :: new ( value) } )
1445
+ }
1446
+ }
1447
+
1448
+ impl < ' tcx , ' lt > fmt:: Debug for TyIVar < ' tcx , ' lt > {
1449
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1450
+ match self . get ( ) {
1451
+ Some ( val) => write ! ( f, "TyIVar({:?})" , val) ,
1452
+ None => f. write_str ( "TyIVar(<unfulfilled>)" )
1453
+ }
1454
+ }
1455
+ }
1456
+
1398
1457
/// An entry in the type interner.
1399
1458
pub struct InternedTy < ' tcx > {
1400
1459
ty : Ty < ' tcx >
@@ -3210,44 +3269,69 @@ bitflags! {
3210
3269
const IS_PHANTOM_DATA = 1 << 1 ,
3211
3270
const IS_DTORCK = 1 << 2 , // is this a dtorck type?
3212
3271
const IS_DTORCK_VALID = 1 << 3 ,
3272
+ const IS_ENUM = 1 << 4
3213
3273
}
3214
3274
}
3215
3275
3216
- /// The definition of an abstract data type - a struct or enum.
3217
- pub struct ADTDef < ' tcx > {
3276
+ pub type ADTDef < ' tcx > = ADTDef_ < ' tcx , ' static > ;
3277
+
3278
+ pub struct VariantDef < ' tcx , ' lt : ' tcx > {
3279
+ pub did : DefId ,
3280
+ pub name : Name , // struct's name if this is a struct
3281
+ pub disr_val : Disr ,
3282
+ pub fields : Vec < FieldDef < ' tcx , ' lt > >
3283
+ }
3284
+
3285
+ pub struct FieldDef < ' tcx , ' lt : ' tcx > {
3286
+ pub did : DefId ,
3287
+ pub name : Name , // XXX if tuple-like
3288
+ pub vis : ast:: Visibility ,
3289
+ // TyIVar is used here to allow for
3290
+ ty : TyIVar < ' tcx , ' lt >
3291
+ }
3292
+
3293
+ /// The definition of an abstract data type - a struct or enum. 'lt
3294
+ /// is here so 'tcx can be variant.
3295
+ pub struct ADTDef_ < ' tcx , ' lt : ' tcx > {
3218
3296
pub did : DefId ,
3297
+ pub variants : Vec < VariantDef < ' tcx , ' lt > > ,
3219
3298
flags : Cell < ADTFlags > ,
3220
- marker : :: std:: marker:: PhantomData < & ' tcx ( ) > ,
3221
3299
}
3222
3300
3223
- impl < ' tcx > PartialEq for ADTDef < ' tcx > {
3301
+ impl < ' tcx , ' lt > PartialEq for ADTDef_ < ' tcx , ' lt > {
3224
3302
// ADTDef are always interned and this is part of TyS equality
3225
3303
#[ inline]
3226
3304
fn eq ( & self , other : & Self ) -> bool { self as * const _ == other as * const _ }
3227
3305
}
3228
3306
3229
- impl < ' tcx > Eq for ADTDef < ' tcx > { }
3307
+ impl < ' tcx , ' lt > Eq for ADTDef_ < ' tcx , ' lt > { }
3230
3308
3231
- impl < ' tcx > Hash for ADTDef < ' tcx > {
3309
+ impl < ' tcx , ' lt > Hash for ADTDef_ < ' tcx , ' lt > {
3232
3310
#[ inline]
3233
3311
fn hash < H : Hasher > ( & self , s : & mut H ) {
3234
3312
( self as * const ADTDef ) . hash ( s)
3235
3313
}
3236
3314
}
3237
3315
3238
- impl < ' tcx > ADTDef < ' tcx > {
3239
- fn new ( tcx : & ctxt < ' tcx > , did : DefId ) -> Self {
3316
+ #[ derive( Copy , Clone , Debug ) ]
3317
+ pub enum ADTKind { Struct , Enum }
3318
+
3319
+ impl < ' tcx , ' lt > ADTDef_ < ' tcx , ' lt > {
3320
+ fn new ( tcx : & ctxt < ' tcx > , did : DefId , kind : ADTKind ) -> Self {
3240
3321
let mut flags = ADTFlags :: NO_ADT_FLAGS ;
3241
3322
if tcx. has_attr ( did, "fundamental" ) {
3242
3323
flags = flags | ADTFlags :: IS_FUNDAMENTAL ;
3243
3324
}
3244
3325
if Some ( did) == tcx. lang_items . phantom_data ( ) {
3245
3326
flags = flags | ADTFlags :: IS_PHANTOM_DATA ;
3246
3327
}
3328
+ if let ADTKind :: Enum = kind {
3329
+ flags = flags | ADTFlags :: IS_ENUM ;
3330
+ }
3247
3331
ADTDef {
3248
3332
did : did,
3333
+ variants : vec ! [ ] ,
3249
3334
flags : Cell :: new ( flags) ,
3250
- marker : :: std:: marker:: PhantomData
3251
3335
}
3252
3336
}
3253
3337
@@ -3258,6 +3342,15 @@ impl<'tcx> ADTDef<'tcx> {
3258
3342
self . flags . set ( self . flags . get ( ) | ADTFlags :: IS_DTORCK_VALID )
3259
3343
}
3260
3344
3345
+ #[ inline]
3346
+ pub fn adt_kind ( & self ) -> ADTKind {
3347
+ if self . flags . get ( ) . intersects ( ADTFlags :: IS_ENUM ) {
3348
+ ADTKind :: Enum
3349
+ } else {
3350
+ ADTKind :: Struct
3351
+ }
3352
+ }
3353
+
3261
3354
#[ inline]
3262
3355
pub fn is_dtorck ( & ' tcx self , tcx : & ctxt < ' tcx > ) -> bool {
3263
3356
if !self . flags . get ( ) . intersects ( ADTFlags :: IS_DTORCK_VALID ) {
0 commit comments