@@ -9,7 +9,7 @@ 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 } ;
1414use crate :: ty:: layout:: VariantIdx ;
1515use crate :: util:: captures:: Captures ;
@@ -18,6 +18,7 @@ use crate::mir::interpret::{Scalar, Pointer};
1818use smallvec:: SmallVec ;
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 } ;
@@ -478,14 +479,35 @@ impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> {
478479 const RETURNED_NAME : & ' static str = "Returned" ;
479480 const POISONED_NAME : & ' static str = "Panicked" ;
480481
481- /// The variants of this Generator.
482+ /// The valid variant indices of this Generator.
482483 #[ inline]
483- pub fn variants ( & self , def_id : DefId , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) ->
484- impl Iterator < Item = VariantIdx >
485- {
484+ pub fn variant_range ( & self , def_id : DefId , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> Range < VariantIdx > {
486485 // FIXME requires optimized MIR
487486 let num_variants = self . state_tys ( def_id, tcx) . count ( ) ;
488- ( 0 ..num_variants) . map ( VariantIdx :: new)
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+ } )
489511 }
490512
491513 /// Calls `f` with a reference to the name of the enumerator for the given
@@ -503,7 +525,7 @@ impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> {
503525 f ( name)
504526 }
505527
506- /// The type of the state " discriminant" used in the generator type.
528+ /// The type of the state discriminant used in the generator type.
507529 #[ inline]
508530 pub fn discr_ty ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> Ty < ' tcx > {
509531 tcx. types . u32
@@ -2028,6 +2050,34 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
20282050 }
20292051 }
20302052
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+
20312081 /// Push onto `out` the regions directly referenced from this type (but not
20322082 /// types reachable from this type via `walk_tys`). This ignores late-bound
20332083 /// regions binders.
0 commit comments