@@ -550,11 +550,105 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> {
550
550
state : & State < FlatSet < Scalar > > ,
551
551
map : & Map ,
552
552
) -> Option < ConstantKind < ' tcx > > {
553
- let FlatSet :: Elem ( Scalar :: Int ( value) ) = state. get ( place. as_ref ( ) , & map) else {
554
- return None ;
555
- } ;
556
553
let ty = place. ty ( self . local_decls , self . patch . tcx ) . ty ;
557
- Some ( ConstantKind :: Val ( ConstValue :: Scalar ( value. into ( ) ) , ty) )
554
+ let place = map. find ( place. as_ref ( ) ) ?;
555
+ if let FlatSet :: Elem ( Scalar :: Int ( value) ) = state. get_idx ( place, map) {
556
+ Some ( ConstantKind :: Val ( ConstValue :: Scalar ( value. into ( ) ) , ty) )
557
+ } else {
558
+ let valtree = self . try_make_valtree ( place, ty, state, map) ?;
559
+ let constant = ty:: Const :: new_value ( self . patch . tcx , valtree, ty) ;
560
+ Some ( ConstantKind :: Ty ( constant) )
561
+ }
562
+ }
563
+
564
+ fn try_make_valtree (
565
+ & self ,
566
+ place : PlaceIndex ,
567
+ ty : Ty < ' tcx > ,
568
+ state : & State < FlatSet < Scalar > > ,
569
+ map : & Map ,
570
+ ) -> Option < ty:: ValTree < ' tcx > > {
571
+ let tcx = self . patch . tcx ;
572
+ match ty. kind ( ) {
573
+ // ZSTs.
574
+ ty:: FnDef ( ..) => Some ( ty:: ValTree :: zst ( ) ) ,
575
+
576
+ // Scalars.
577
+ ty:: Bool | ty:: Int ( _) | ty:: Uint ( _) | ty:: Float ( _) | ty:: Char => {
578
+ if let FlatSet :: Elem ( Scalar :: Int ( value) ) = state. get_idx ( place, map) {
579
+ Some ( ty:: ValTree :: Leaf ( value) )
580
+ } else {
581
+ None
582
+ }
583
+ }
584
+
585
+ // Unsupported for now.
586
+ ty:: Array ( _, _) => None ,
587
+
588
+ ty:: Tuple ( elem_tys) => {
589
+ let branches = elem_tys
590
+ . iter ( )
591
+ . enumerate ( )
592
+ . map ( |( i, ty) | {
593
+ let field = map. apply ( place, TrackElem :: Field ( FieldIdx :: from_usize ( i) ) ) ?;
594
+ self . try_make_valtree ( field, ty, state, map)
595
+ } )
596
+ . collect :: < Option < Vec < _ > > > ( ) ?;
597
+ Some ( ty:: ValTree :: Branch ( tcx. arena . alloc_from_iter ( branches. into_iter ( ) ) ) )
598
+ }
599
+
600
+ ty:: Adt ( def, args) => {
601
+ if def. is_union ( ) {
602
+ return None ;
603
+ }
604
+
605
+ let ( variant_idx, variant_def, variant_place) = if def. is_enum ( ) {
606
+ let discr = map. apply ( place, TrackElem :: Discriminant ) ?;
607
+ let FlatSet :: Elem ( Scalar :: Int ( discr) ) = state. get_idx ( discr, map) else {
608
+ return None ;
609
+ } ;
610
+ let discr_bits = discr. assert_bits ( discr. size ( ) ) ;
611
+ let ( variant, _) =
612
+ def. discriminants ( tcx) . find ( |( _, var) | discr_bits == var. val ) ?;
613
+ let variant_place = map. apply ( place, TrackElem :: Variant ( variant) ) ?;
614
+ let variant_int = ty:: ValTree :: Leaf ( variant. as_u32 ( ) . into ( ) ) ;
615
+ ( Some ( variant_int) , def. variant ( variant) , variant_place)
616
+ } else {
617
+ ( None , def. non_enum_variant ( ) , place)
618
+ } ;
619
+
620
+ let branches = variant_def
621
+ . fields
622
+ . iter_enumerated ( )
623
+ . map ( |( i, field) | {
624
+ let ty = field. ty ( tcx, args) ;
625
+ let field = map. apply ( variant_place, TrackElem :: Field ( i) ) ?;
626
+ self . try_make_valtree ( field, ty, state, map)
627
+ } )
628
+ . collect :: < Option < Vec < _ > > > ( ) ?;
629
+ Some ( ty:: ValTree :: Branch (
630
+ tcx. arena . alloc_from_iter ( variant_idx. into_iter ( ) . chain ( branches) ) ,
631
+ ) )
632
+ }
633
+
634
+ // Do not attempt to support indirection in constants.
635
+ ty:: Ref ( ..) | ty:: RawPtr ( ..) | ty:: FnPtr ( ..) | ty:: Str | ty:: Slice ( _) => None ,
636
+
637
+ ty:: Never
638
+ | ty:: Foreign ( ..)
639
+ | ty:: Alias ( ..)
640
+ | ty:: Param ( _)
641
+ | ty:: Bound ( ..)
642
+ | ty:: Placeholder ( ..)
643
+ | ty:: Closure ( ..)
644
+ | ty:: Generator ( ..)
645
+ | ty:: Dynamic ( ..) => None ,
646
+
647
+ ty:: Error ( _)
648
+ | ty:: Infer ( ..)
649
+ | ty:: GeneratorWitness ( ..)
650
+ | ty:: GeneratorWitnessMIR ( ..) => bug ! ( ) ,
651
+ }
558
652
}
559
653
}
560
654
0 commit comments