@@ -9,7 +9,7 @@ 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
14
use crate :: ty:: layout:: VariantIdx ;
15
15
use crate :: util:: captures:: Captures ;
@@ -18,6 +18,7 @@ use crate::mir::interpret::{Scalar, Pointer};
18
18
use smallvec:: SmallVec ;
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 } ;
@@ -478,14 +479,35 @@ impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> {
478
479
const RETURNED_NAME : & ' static str = "Returned" ;
479
480
const POISONED_NAME : & ' static str = "Panicked" ;
480
481
481
- /// The variants of this Generator.
482
+ /// The valid variant indices of this Generator.
482
483
#[ 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 > {
486
485
// FIXME requires optimized MIR
487
486
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
+ } )
489
511
}
490
512
491
513
/// Calls `f` with a reference to the name of the enumerator for the given
@@ -503,7 +525,7 @@ impl<'a, 'gcx, 'tcx> GeneratorSubsts<'tcx> {
503
525
f ( name)
504
526
}
505
527
506
- /// The type of the state " discriminant" used in the generator type.
528
+ /// The type of the state discriminant used in the generator type.
507
529
#[ inline]
508
530
pub fn discr_ty ( & self , tcx : TyCtxt < ' a , ' gcx , ' tcx > ) -> Ty < ' tcx > {
509
531
tcx. types . u32
@@ -2028,6 +2050,34 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
2028
2050
}
2029
2051
}
2030
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
+
2031
2081
/// Push onto `out` the regions directly referenced from this type (but not
2032
2082
/// types reachable from this type via `walk_tys`). This ignores late-bound
2033
2083
/// regions binders.
0 commit comments