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