@@ -9,15 +9,16 @@ use polonius_engine::Atom;
9
9
use rustc_data_structures:: indexed_vec:: Idx ;
10
10
use rustc_macros:: HashStable ;
11
11
use crate :: ty:: subst:: { InternalSubsts , Subst , SubstsRef , Kind , UnpackedKind } ;
12
- use crate :: ty:: { self , AdtDef , DefIdTree , TypeFlags , Ty , TyCtxt , TypeFoldable } ;
12
+ use crate :: ty:: { self , AdtDef , Discr , DefIdTree , TypeFlags , Ty , TyCtxt , TypeFoldable } ;
13
13
use crate :: ty:: { List , TyS , ParamEnvAnd , ParamEnv } ;
14
+ use crate :: ty:: layout:: VariantIdx ;
14
15
use crate :: util:: captures:: Captures ;
15
16
use crate :: mir:: interpret:: { Scalar , Pointer } ;
16
17
17
18
use smallvec:: SmallVec ;
18
- use std:: iter;
19
19
use std:: cmp:: Ordering ;
20
20
use std:: marker:: PhantomData ;
21
+ use std:: ops:: Range ;
21
22
use rustc_target:: spec:: abi;
22
23
use syntax:: ast:: { self , Ident } ;
23
24
use syntax:: symbol:: { keywords, InternedString } ;
@@ -298,14 +299,10 @@ static_assert!(MEM_SIZE_OF_TY_KIND: ::std::mem::size_of::<TyKind<'_>>() == 24);
298
299
///
299
300
/// ## Generators
300
301
///
301
- /// Perhaps surprisingly, `ClosureSubsts` are also used for
302
- /// generators. In that case, what is written above is only half-true
303
- /// -- the set of type parameters is similar, but the role of CK and
304
- /// CS are different. CK represents the "yield type" and CS
305
- /// represents the "return type" of the generator.
306
- ///
307
- /// It'd be nice to split this struct into ClosureSubsts and
308
- /// GeneratorSubsts, I believe. -nmatsakis
302
+ /// Generators are handled similarly in `GeneratorSubsts`. The set of
303
+ /// type parameters is similar, but the role of CK and CS are
304
+ /// different. CK represents the "yield type" and CS represents the
305
+ /// "return type" of the generator.
309
306
#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ,
310
307
Debug , RustcEncodable , RustcDecodable , HashStable ) ]
311
308
pub struct ClosureSubsts < ' tcx > {
@@ -391,6 +388,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
391
388
}
392
389
}
393
390
391
+ /// Similar to `ClosureSubsts`; see the above documentation for more.
394
392
#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash , Debug ,
395
393
RustcEncodable , RustcDecodable , HashStable ) ]
396
394
pub struct GeneratorSubsts < ' tcx > {
@@ -470,33 +468,91 @@ impl<'tcx> GeneratorSubsts<'tcx> {
470
468
}
471
469
472
470
impl < ' a , ' gcx , ' tcx > GeneratorSubsts < ' tcx > {
471
+ /// Generator have not been resumed yet
472
+ pub const UNRESUMED : usize = 0 ;
473
+ /// Generator has returned / is completed
474
+ pub const RETURNED : usize = 1 ;
475
+ /// Generator has been poisoned
476
+ pub const POISONED : usize = 2 ;
477
+
478
+ const UNRESUMED_NAME : & ' static str = "Unresumed" ;
479
+ const RETURNED_NAME : & ' static str = "Returned" ;
480
+ const POISONED_NAME : & ' static str = "Panicked" ;
481
+
482
+ /// The valid variant indices of this Generator.
483
+ #[ inline]
484
+ pub fn variant_range ( & self , def_id : DefId , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> Range < VariantIdx > {
485
+ // FIXME requires optimized MIR
486
+ let num_variants = self . state_tys ( def_id, tcx) . count ( ) ;
487
+ ( VariantIdx :: new ( 0 ) ..VariantIdx :: new ( num_variants) )
488
+ }
489
+
490
+ /// The discriminant for the given variant. Panics if the variant_index is
491
+ /// out of range.
492
+ #[ inline]
493
+ pub fn discriminant_for_variant (
494
+ & self , def_id : DefId , tcx : TyCtxt < ' a , ' gcx , ' tcx > , variant_index : VariantIdx
495
+ ) -> Discr < ' tcx > {
496
+ // Generators don't support explicit discriminant values, so they are
497
+ // the same as the variant index.
498
+ assert ! ( self . variant_range( def_id, tcx) . contains( & variant_index) ) ;
499
+ Discr { val : variant_index. as_usize ( ) as u128 , ty : self . discr_ty ( tcx) }
500
+ }
501
+
502
+ /// The set of all discriminants for the Generator, enumerated with their
503
+ /// variant indices.
504
+ #[ inline]
505
+ pub fn discriminants (
506
+ & ' a self , def_id : DefId , tcx : TyCtxt < ' a , ' gcx , ' tcx >
507
+ ) -> impl Iterator < Item =( VariantIdx , Discr < ' tcx > ) > + Captures < ' gcx > + ' a {
508
+ self . variant_range ( def_id, tcx) . map ( move |index| {
509
+ ( index, Discr { val : index. as_usize ( ) as u128 , ty : self . discr_ty ( tcx) } )
510
+ } )
511
+ }
512
+
513
+ /// Calls `f` with a reference to the name of the enumerator for the given
514
+ /// variant `v`.
515
+ #[ inline]
516
+ pub fn map_variant_name < R > ( & self , v : VariantIdx , f : impl FnOnce ( & str ) -> R ) -> R {
517
+ let name = match v. as_usize ( ) {
518
+ Self :: UNRESUMED => Self :: UNRESUMED_NAME ,
519
+ Self :: RETURNED => Self :: RETURNED_NAME ,
520
+ Self :: POISONED => Self :: POISONED_NAME ,
521
+ _ => {
522
+ return f ( & format ! ( "variant#{}" , v. as_usize( ) ) ) ;
523
+ }
524
+ } ;
525
+ f ( name)
526
+ }
527
+
528
+ /// The type of the state discriminant used in the generator type.
529
+ #[ inline]
530
+ pub fn discr_ty ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> Ty < ' tcx > {
531
+ tcx. types . u32
532
+ }
533
+
473
534
/// This returns the types of the MIR locals which had to be stored across suspension points.
474
535
/// It is calculated in rustc_mir::transform::generator::StateTransform.
475
536
/// All the types here must be in the tuple in GeneratorInterior.
476
- pub fn state_tys (
477
- self ,
478
- def_id : DefId ,
479
- tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
480
- ) -> impl Iterator < Item =Ty < ' tcx > > + Captures < ' gcx > + ' a {
481
- let state = tcx. generator_layout ( def_id) . fields . iter ( ) ;
482
- state. map ( move |d| d. ty . subst ( tcx, self . substs ) )
483
- }
484
-
485
- /// This is the types of the fields of a generate which
486
- /// is available before the generator transformation.
487
- /// It includes the upvars and the state discriminant which is u32.
488
- pub fn pre_transforms_tys ( self , def_id : DefId , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) ->
489
- impl Iterator < Item =Ty < ' tcx > > + ' a
537
+ ///
538
+ /// The locals are grouped by their variant number. Note that some locals may
539
+ /// be repeated in multiple variants.
540
+ #[ inline]
541
+ pub fn state_tys ( self , def_id : DefId , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) ->
542
+ impl Iterator < Item =impl Iterator < Item =Ty < ' tcx > > + Captures < ' gcx > + ' a >
490
543
{
491
- self . upvar_tys ( def_id, tcx) . chain ( iter:: once ( tcx. types . u32 ) )
544
+ tcx. generator_layout ( def_id)
545
+ . variant_fields . iter ( )
546
+ . map ( move |v| v. iter ( ) . map ( move |d| d. ty . subst ( tcx, self . substs ) ) )
492
547
}
493
548
494
- /// This is the types of all the fields stored in a generator.
495
- /// It includes the upvars, state types and the state discriminant which is u32.
496
- pub fn field_tys ( self , def_id : DefId , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) ->
497
- impl Iterator < Item =Ty < ' tcx > > + Captures < ' gcx > + ' a
549
+ /// This is the types of the fields of a generator which are not stored in a
550
+ /// variant.
551
+ #[ inline]
552
+ pub fn prefix_tys ( self , def_id : DefId , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) ->
553
+ impl Iterator < Item =Ty < ' tcx > > + ' a
498
554
{
499
- self . pre_transforms_tys ( def_id, tcx) . chain ( self . state_tys ( def_id , tcx ) )
555
+ self . upvar_tys ( def_id, tcx)
500
556
}
501
557
}
502
558
@@ -1994,6 +2050,34 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
1994
2050
}
1995
2051
}
1996
2052
2053
+ /// If the type contains variants, returns the valid range of variant indices.
2054
+ /// FIXME This requires the optimized MIR in the case of generators.
2055
+ #[ inline]
2056
+ pub fn variant_range ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> Option < Range < VariantIdx > > {
2057
+ match self . sty {
2058
+ TyKind :: Adt ( adt, _) => Some ( adt. variant_range ( ) ) ,
2059
+ TyKind :: Generator ( def_id, substs, _) => Some ( substs. variant_range ( def_id, tcx) ) ,
2060
+ _ => None ,
2061
+ }
2062
+ }
2063
+
2064
+ /// If the type contains variants, returns the variant for `variant_index`.
2065
+ /// Panics if `variant_index` is out of range.
2066
+ /// FIXME This requires the optimized MIR in the case of generators.
2067
+ #[ inline]
2068
+ pub fn discriminant_for_variant (
2069
+ & self ,
2070
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
2071
+ variant_index : VariantIdx
2072
+ ) -> Option < Discr < ' tcx > > {
2073
+ match self . sty {
2074
+ TyKind :: Adt ( adt, _) => Some ( adt. discriminant_for_variant ( tcx, variant_index) ) ,
2075
+ TyKind :: Generator ( def_id, substs, _) =>
2076
+ Some ( substs. discriminant_for_variant ( def_id, tcx, variant_index) ) ,
2077
+ _ => None ,
2078
+ }
2079
+ }
2080
+
1997
2081
/// Push onto `out` the regions directly referenced from this type (but not
1998
2082
/// types reachable from this type via `walk_tys`). This ignores late-bound
1999
2083
/// regions binders.
0 commit comments