@@ -15,7 +15,7 @@ use rustc_middle::{
15
15
mir:: { Field , Local , Place , ProjectionElem } ,
16
16
ty:: { self , Ty , TypeAndMut , VariantDef } ,
17
17
} ;
18
- use rustc_target:: abi:: { TagEncoding , Variants } ;
18
+ use rustc_target:: abi:: { TagEncoding , VariantIdx , Variants } ;
19
19
use tracing:: { debug, trace, warn} ;
20
20
21
21
/// A projection in Kani can either be to a type (the normal case),
@@ -24,6 +24,7 @@ use tracing::{debug, trace, warn};
24
24
pub enum TypeOrVariant < ' tcx > {
25
25
Type ( Ty < ' tcx > ) ,
26
26
Variant ( & ' tcx VariantDef ) ,
27
+ GeneratorVariant ( VariantIdx ) ,
27
28
}
28
29
29
30
/// A struct for storing the data for passing to `codegen_unimplemented`
@@ -129,7 +130,7 @@ impl<'tcx> ProjectedPlace<'tcx> {
129
130
}
130
131
}
131
132
// TODO: handle Variant https://github.com/model-checking/kani/issues/448
132
- TypeOrVariant :: Variant ( _) => None ,
133
+ TypeOrVariant :: Variant ( _) | TypeOrVariant :: GeneratorVariant ( _ ) => None ,
133
134
}
134
135
}
135
136
@@ -197,7 +198,7 @@ impl<'tcx> TypeOrVariant<'tcx> {
197
198
pub fn monomorphize ( self , ctx : & GotocCtx < ' tcx > ) -> Self {
198
199
match self {
199
200
TypeOrVariant :: Type ( t) => TypeOrVariant :: Type ( ctx. monomorphize ( t) ) ,
200
- TypeOrVariant :: Variant ( _) => self ,
201
+ TypeOrVariant :: Variant ( _) | TypeOrVariant :: GeneratorVariant ( _ ) => self ,
201
202
}
202
203
}
203
204
}
@@ -207,6 +208,9 @@ impl<'tcx> TypeOrVariant<'tcx> {
207
208
match self {
208
209
TypeOrVariant :: Type ( t) => * t,
209
210
TypeOrVariant :: Variant ( v) => panic ! ( "expect a type but variant is found: {:?}" , v) ,
211
+ TypeOrVariant :: GeneratorVariant ( v) => {
212
+ panic ! ( "expect a type but generator variant is found: {:?}" , v)
213
+ }
210
214
}
211
215
}
212
216
@@ -215,6 +219,9 @@ impl<'tcx> TypeOrVariant<'tcx> {
215
219
match self {
216
220
TypeOrVariant :: Type ( t) => panic ! ( "expect a variant but type is found: {:?}" , t) ,
217
221
TypeOrVariant :: Variant ( v) => v,
222
+ TypeOrVariant :: GeneratorVariant ( v) => {
223
+ panic ! ( "expect a variant but generator variant found {:?}" , v)
224
+ }
218
225
}
219
226
}
220
227
}
@@ -269,12 +276,12 @@ impl<'tcx> GotocCtx<'tcx> {
269
276
Ok ( res. member ( & field. name . to_string ( ) , & self . symbol_table ) )
270
277
}
271
278
ty:: Closure ( ..) => Ok ( res. member ( & f. index ( ) . to_string ( ) , & self . symbol_table ) ) ,
272
- ty:: Generator ( ..) => Err ( UnimplementedData :: new (
273
- "ty::Generator" ,
274
- "https://github.com/model-checking/kani/issues/416" ,
275
- Type :: code ( vec ! [ ] , Type :: empty ( ) ) ,
276
- * res . location ( ) ,
277
- ) ) ,
279
+ ty:: Generator ( ..) => {
280
+ let field_name = self . generator_field_name ( f . index ( ) . into ( ) ) ;
281
+ Ok ( res
282
+ . member ( "direct_fields" , & self . symbol_table )
283
+ . member ( field_name , & self . symbol_table ) )
284
+ }
278
285
_ => unimplemented ! ( ) ,
279
286
}
280
287
}
@@ -283,6 +290,10 @@ impl<'tcx> GotocCtx<'tcx> {
283
290
let field = & v. fields [ f. index ( ) ] ;
284
291
Ok ( res. member ( & field. name . to_string ( ) , & self . symbol_table ) )
285
292
}
293
+ TypeOrVariant :: GeneratorVariant ( _var_idx) => {
294
+ let field_name = self . generator_field_name ( f. index ( ) . into ( ) ) ;
295
+ Ok ( res. member ( field_name, & self . symbol_table ) )
296
+ }
286
297
}
287
298
}
288
299
@@ -498,33 +509,43 @@ impl<'tcx> GotocCtx<'tcx> {
498
509
ProjectionElem :: Downcast ( _, idx) => {
499
510
// downcast converts a variable of an enum type to one of its discriminated cases
500
511
let t = before. mir_typ ( ) ;
501
- match t. kind ( ) {
512
+ let ( case_name , type_or_variant ) = match t. kind ( ) {
502
513
ty:: Adt ( def, _) => {
503
- let variant = def. variants ( ) . get ( idx) . unwrap ( ) ;
504
- let case_name = variant. name . to_string ( ) ;
505
- let typ = TypeOrVariant :: Variant ( variant) ;
506
- let expr = match & self . layout_of ( t) . variants {
507
- Variants :: Single { .. } => before. goto_expr ,
508
- Variants :: Multiple { tag_encoding, .. } => match tag_encoding {
509
- TagEncoding :: Direct => before
510
- . goto_expr
511
- . member ( "cases" , & self . symbol_table )
512
- . member ( & case_name, & self . symbol_table ) ,
513
- TagEncoding :: Niche { .. } => {
514
- before. goto_expr . member ( & case_name, & self . symbol_table )
515
- }
516
- } ,
517
- } ;
518
- ProjectedPlace :: try_new (
519
- expr,
520
- typ,
521
- before. fat_ptr_goto_expr ,
522
- before. fat_ptr_mir_typ ,
523
- self ,
524
- )
514
+ let variant = def. variant ( idx) ;
515
+ ( variant. name . as_str ( ) . into ( ) , TypeOrVariant :: Variant ( variant) )
525
516
}
526
- _ => unreachable ! ( "it's a bug to reach here!" ) ,
527
- }
517
+ ty:: Generator ( ..) => {
518
+ ( self . generator_variant_name ( idx) , TypeOrVariant :: GeneratorVariant ( idx) )
519
+ }
520
+ _ => unreachable ! (
521
+ "cannot downcast {:?} to a variant (only enums and generators can)" ,
522
+ & t. kind( )
523
+ ) ,
524
+ } ;
525
+ let layout = self . layout_of ( t) ;
526
+ let expr = match & layout. variants {
527
+ Variants :: Single { .. } => before. goto_expr ,
528
+ Variants :: Multiple { tag_encoding, .. } => match tag_encoding {
529
+ TagEncoding :: Direct => {
530
+ let cases = if t. is_generator ( ) {
531
+ before. goto_expr
532
+ } else {
533
+ before. goto_expr . member ( "cases" , & self . symbol_table )
534
+ } ;
535
+ cases. member ( case_name, & self . symbol_table )
536
+ }
537
+ TagEncoding :: Niche { .. } => {
538
+ before. goto_expr . member ( case_name, & self . symbol_table )
539
+ }
540
+ } ,
541
+ } ;
542
+ ProjectedPlace :: try_new (
543
+ expr,
544
+ type_or_variant,
545
+ before. fat_ptr_goto_expr ,
546
+ before. fat_ptr_mir_typ ,
547
+ self ,
548
+ )
528
549
}
529
550
ProjectionElem :: OpaqueCast ( ty) => ProjectedPlace :: try_new (
530
551
before. goto_expr . cast_to ( self . codegen_ty ( ty) ) ,
0 commit comments