@@ -9,15 +9,16 @@ use polonius_engine::Atom;
99use rustc_data_structures:: indexed_vec:: Idx ;
1010use rustc_macros:: HashStable ;
1111use 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 } ;
1313use crate :: ty:: { List , TyS , ParamEnvAnd , ParamEnv } ;
14+ use crate :: ty:: layout:: VariantIdx ;
1415use crate :: util:: captures:: Captures ;
1516use crate :: mir:: interpret:: { Scalar , Pointer } ;
1617
1718use smallvec:: SmallVec ;
18- use std:: iter;
1919use std:: cmp:: Ordering ;
2020use std:: marker:: PhantomData ;
21+ use std:: ops:: Range ;
2122use rustc_target:: spec:: abi;
2223use syntax:: ast:: { self , Ident } ;
2324use syntax:: symbol:: { keywords, InternedString } ;
@@ -298,14 +299,10 @@ static_assert!(MEM_SIZE_OF_TY_KIND: ::std::mem::size_of::<TyKind<'_>>() == 24);
298299///
299300/// ## Generators
300301///
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.
309306#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash ,
310307 Debug , RustcEncodable , RustcDecodable , HashStable ) ]
311308pub struct ClosureSubsts < ' tcx > {
@@ -391,6 +388,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
391388 }
392389}
393390
391+ /// Similar to `ClosureSubsts`; see the above documentation for more.
394392#[ derive( Copy , Clone , PartialEq , Eq , PartialOrd , Ord , Hash , Debug ,
395393 RustcEncodable , RustcDecodable , HashStable ) ]
396394pub struct GeneratorSubsts < ' tcx > {
@@ -470,33 +468,91 @@ impl<'tcx> GeneratorSubsts<'tcx> {
470468}
471469
472470impl < ' 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+
473534 /// This returns the types of the MIR locals which had to be stored across suspension points.
474535 /// It is calculated in rustc_mir::transform::generator::StateTransform.
475536 /// 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 >
490543 {
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 ) ) )
492547 }
493548
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
498554 {
499- self . pre_transforms_tys ( def_id, tcx) . chain ( self . state_tys ( def_id , tcx ) )
555+ self . upvar_tys ( def_id, tcx)
500556 }
501557}
502558
@@ -1994,6 +2050,34 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
19942050 }
19952051 }
19962052
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+
19972081 /// Push onto `out` the regions directly referenced from this type (but not
19982082 /// types reachable from this type via `walk_tys`). This ignores late-bound
19992083 /// regions binders.
0 commit comments