@@ -463,7 +463,19 @@ impl<V: Clone> Clone for State<V> {
463463 }
464464}
465465
466- impl < V : Clone + HasTop + HasBottom > State < V > {
466+ impl < V : Clone > State < V > {
467+ pub fn new ( init : V , map : & Map ) -> State < V > {
468+ let values = IndexVec :: from_elem_n ( init, map. value_count ) ;
469+ State ( StateData :: Reachable ( values) )
470+ }
471+
472+ pub fn all ( & self , f : impl Fn ( & V ) -> bool ) -> bool {
473+ match self . 0 {
474+ StateData :: Unreachable => true ,
475+ StateData :: Reachable ( ref values) => values. iter ( ) . all ( f) ,
476+ }
477+ }
478+
467479 pub fn is_reachable ( & self ) -> bool {
468480 matches ! ( & self . 0 , StateData :: Reachable ( _) )
469481 }
@@ -472,7 +484,10 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
472484 self . 0 = StateData :: Unreachable ;
473485 }
474486
475- pub fn flood_all ( & mut self ) {
487+ pub fn flood_all ( & mut self )
488+ where
489+ V : HasTop ,
490+ {
476491 self . flood_all_with ( V :: TOP )
477492 }
478493
@@ -482,27 +497,40 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
482497 }
483498
484499 pub fn flood_with ( & mut self , place : PlaceRef < ' _ > , map : & Map , value : V ) {
485- let StateData :: Reachable ( values) = & mut self . 0 else { return } ;
486- map. for_each_aliasing_place ( place, None , & mut |vi| {
487- values[ vi] = value. clone ( ) ;
488- } ) ;
500+ self . flood_with_extra ( place, None , map, value)
489501 }
490502
491- pub fn flood ( & mut self , place : PlaceRef < ' _ > , map : & Map ) {
503+ pub fn flood ( & mut self , place : PlaceRef < ' _ > , map : & Map )
504+ where
505+ V : HasTop ,
506+ {
492507 self . flood_with ( place, map, V :: TOP )
493508 }
494509
495510 pub fn flood_discr_with ( & mut self , place : PlaceRef < ' _ > , map : & Map , value : V ) {
496- let StateData :: Reachable ( values) = & mut self . 0 else { return } ;
497- map. for_each_aliasing_place ( place, Some ( TrackElem :: Discriminant ) , & mut |vi| {
498- values[ vi] = value. clone ( ) ;
499- } ) ;
511+ self . flood_with_extra ( place, Some ( TrackElem :: Discriminant ) , map, value)
500512 }
501513
502- pub fn flood_discr ( & mut self , place : PlaceRef < ' _ > , map : & Map ) {
514+ pub fn flood_discr ( & mut self , place : PlaceRef < ' _ > , map : & Map )
515+ where
516+ V : HasTop ,
517+ {
503518 self . flood_discr_with ( place, map, V :: TOP )
504519 }
505520
521+ pub fn flood_with_extra (
522+ & mut self ,
523+ place : PlaceRef < ' _ > ,
524+ tail_elem : Option < TrackElem > ,
525+ map : & Map ,
526+ value : V ,
527+ ) {
528+ let StateData :: Reachable ( values) = & mut self . 0 else { return } ;
529+ map. for_each_aliasing_place ( place, tail_elem, & mut |vi| {
530+ values[ vi] = value. clone ( ) ;
531+ } ) ;
532+ }
533+
506534 /// Low-level method that assigns to a place.
507535 /// This does nothing if the place is not tracked.
508536 ///
@@ -553,44 +581,87 @@ impl<V: Clone + HasTop + HasBottom> State<V> {
553581 }
554582
555583 /// Helper method to interpret `target = result`.
556- pub fn assign ( & mut self , target : PlaceRef < ' _ > , result : ValueOrPlace < V > , map : & Map ) {
584+ pub fn assign ( & mut self , target : PlaceRef < ' _ > , result : ValueOrPlace < V > , map : & Map )
585+ where
586+ V : HasTop ,
587+ {
557588 self . flood ( target, map) ;
558589 if let Some ( target) = map. find ( target) {
559590 self . insert_idx ( target, result, map) ;
560591 }
561592 }
562593
563594 /// Helper method for assignments to a discriminant.
564- pub fn assign_discr ( & mut self , target : PlaceRef < ' _ > , result : ValueOrPlace < V > , map : & Map ) {
595+ pub fn assign_discr ( & mut self , target : PlaceRef < ' _ > , result : ValueOrPlace < V > , map : & Map )
596+ where
597+ V : HasTop ,
598+ {
565599 self . flood_discr ( target, map) ;
566600 if let Some ( target) = map. find_discr ( target) {
567601 self . insert_idx ( target, result, map) ;
568602 }
569603 }
570604
571605 /// Retrieve the value stored for a place, or ⊤ if it is not tracked.
572- pub fn get ( & self , place : PlaceRef < ' _ > , map : & Map ) -> V {
606+ pub fn try_get ( & self , place : PlaceRef < ' _ > , map : & Map ) -> Option < V > {
607+ let place = map. find ( place) ?;
608+ self . try_get_idx ( place, map)
609+ }
610+
611+ /// Retrieve the value stored for a place, or ⊤ if it is not tracked.
612+ pub fn try_get_discr ( & self , place : PlaceRef < ' _ > , map : & Map ) -> Option < V > {
613+ let place = map. find_discr ( place) ?;
614+ self . try_get_idx ( place, map)
615+ }
616+
617+ /// Retrieve the value stored for a place index, or ⊤ if it is not tracked.
618+ pub fn try_get_idx ( & self , place : PlaceIndex , map : & Map ) -> Option < V > {
619+ match & self . 0 {
620+ StateData :: Reachable ( values) => {
621+ map. places [ place] . value_index . map ( |v| values[ v] . clone ( ) )
622+ }
623+ StateData :: Unreachable => {
624+ // Because this is unreachable, we can return any value we want.
625+ None
626+ }
627+ }
628+ }
629+
630+ /// Retrieve the value stored for a place, or ⊤ if it is not tracked.
631+ pub fn get ( & self , place : PlaceRef < ' _ > , map : & Map ) -> V
632+ where
633+ V : HasBottom + HasTop ,
634+ {
573635 map. find ( place) . map ( |place| self . get_idx ( place, map) ) . unwrap_or ( V :: TOP )
574636 }
575637
576638 /// Retrieve the value stored for a place, or ⊤ if it is not tracked.
577- pub fn get_discr ( & self , place : PlaceRef < ' _ > , map : & Map ) -> V {
639+ pub fn get_discr ( & self , place : PlaceRef < ' _ > , map : & Map ) -> V
640+ where
641+ V : HasBottom + HasTop ,
642+ {
578643 match map. find_discr ( place) {
579644 Some ( place) => self . get_idx ( place, map) ,
580645 None => V :: TOP ,
581646 }
582647 }
583648
584649 /// Retrieve the value stored for a place, or ⊤ if it is not tracked.
585- pub fn get_len ( & self , place : PlaceRef < ' _ > , map : & Map ) -> V {
650+ pub fn get_len ( & self , place : PlaceRef < ' _ > , map : & Map ) -> V
651+ where
652+ V : HasBottom + HasTop ,
653+ {
586654 match map. find_len ( place) {
587655 Some ( place) => self . get_idx ( place, map) ,
588656 None => V :: TOP ,
589657 }
590658 }
591659
592660 /// Retrieve the value stored for a place index, or ⊤ if it is not tracked.
593- pub fn get_idx ( & self , place : PlaceIndex , map : & Map ) -> V {
661+ pub fn get_idx ( & self , place : PlaceIndex , map : & Map ) -> V
662+ where
663+ V : HasBottom + HasTop ,
664+ {
594665 match & self . 0 {
595666 StateData :: Reachable ( values) => {
596667 map. places [ place] . value_index . map ( |v| values[ v] . clone ( ) ) . unwrap_or ( V :: TOP )
0 commit comments