@@ -453,36 +453,30 @@ pub enum TerminatorKind<'tcx> {
453453 target : BasicBlock ,
454454 } ,
455455
456- /// jump to branch 0 if this lvalue evaluates to true
457- If {
458- cond : Operand < ' tcx > ,
459- targets : ( BasicBlock , BasicBlock ) ,
460- } ,
461-
462- /// lvalue evaluates to some enum; jump depending on the branch
463- Switch {
464- discr : Lvalue < ' tcx > ,
465- adt_def : & ' tcx AdtDef ,
466- targets : Vec < BasicBlock > ,
467- } ,
468-
469456 /// operand evaluates to an integer; jump depending on its value
470457 /// to one of the targets, and otherwise fallback to `otherwise`
471458 SwitchInt {
472459 /// discriminant value being tested
473- discr : Lvalue < ' tcx > ,
460+ discr : Operand < ' tcx > ,
474461
475462 /// type of value being tested
476463 switch_ty : Ty < ' tcx > ,
477464
478465 /// Possible values. The locations to branch to in each case
479466 /// are found in the corresponding indices from the `targets` vector.
480- values : Vec < ConstVal > ,
481-
482- /// Possible branch sites. The length of this vector should be
483- /// equal to the length of the `values` vector plus 1 -- the
484- /// extra item is the block to branch to if none of the values
485- /// fit.
467+ values : Cow < ' tcx , [ ConstInt ] > ,
468+
469+ /// Possible branch sites. The last element of this vector is used
470+ /// for the otherwise branch, so values.len() == targets.len() + 1
471+ /// should hold.
472+ // This invariant is quite non-obvious and also could be improved.
473+ // One way to make this invariant is to have something like this instead:
474+ //
475+ // branches: Vec<(ConstInt, BasicBlock)>,
476+ // otherwise: Option<BasicBlock> // exhaustive if None
477+ //
478+ // However we’ve decided to keep this as-is until we figure a case
479+ // where some other approach seems to be strictly better than other.
486480 targets : Vec < BasicBlock > ,
487481 } ,
488482
@@ -546,12 +540,21 @@ impl<'tcx> Terminator<'tcx> {
546540}
547541
548542impl < ' tcx > TerminatorKind < ' tcx > {
543+ pub fn if_ < ' a , ' gcx > ( tcx : ty:: TyCtxt < ' a , ' gcx , ' tcx > , cond : Operand < ' tcx > ,
544+ t : BasicBlock , f : BasicBlock ) -> TerminatorKind < ' tcx > {
545+ static BOOL_SWITCH_FALSE : & ' static [ ConstInt ] = & [ ConstInt :: Infer ( 0 ) ] ;
546+ TerminatorKind :: SwitchInt {
547+ discr : cond,
548+ switch_ty : tcx. types . bool ,
549+ values : From :: from ( BOOL_SWITCH_FALSE ) ,
550+ targets : vec ! [ f, t] ,
551+ }
552+ }
553+
549554 pub fn successors ( & self ) -> Cow < [ BasicBlock ] > {
550555 use self :: TerminatorKind :: * ;
551556 match * self {
552557 Goto { target : ref b } => slice:: ref_slice ( b) . into_cow ( ) ,
553- If { targets : ( b1, b2) , .. } => vec ! [ b1, b2] . into_cow ( ) ,
554- Switch { targets : ref b, .. } => b[ ..] . into_cow ( ) ,
555558 SwitchInt { targets : ref b, .. } => b[ ..] . into_cow ( ) ,
556559 Resume => ( & [ ] ) . into_cow ( ) ,
557560 Return => ( & [ ] ) . into_cow ( ) ,
@@ -580,8 +583,6 @@ impl<'tcx> TerminatorKind<'tcx> {
580583 use self :: TerminatorKind :: * ;
581584 match * self {
582585 Goto { target : ref mut b } => vec ! [ b] ,
583- If { targets : ( ref mut b1, ref mut b2) , .. } => vec ! [ b1, b2] ,
584- Switch { targets : ref mut b, .. } => b. iter_mut ( ) . collect ( ) ,
585586 SwitchInt { targets : ref mut b, .. } => b. iter_mut ( ) . collect ( ) ,
586587 Resume => Vec :: new ( ) ,
587588 Return => Vec :: new ( ) ,
@@ -659,8 +660,6 @@ impl<'tcx> TerminatorKind<'tcx> {
659660 use self :: TerminatorKind :: * ;
660661 match * self {
661662 Goto { .. } => write ! ( fmt, "goto" ) ,
662- If { cond : ref lv, .. } => write ! ( fmt, "if({:?})" , lv) ,
663- Switch { discr : ref lv, .. } => write ! ( fmt, "switch({:?})" , lv) ,
664663 SwitchInt { discr : ref lv, .. } => write ! ( fmt, "switchInt({:?})" , lv) ,
665664 Return => write ! ( fmt, "return" ) ,
666665 Resume => write ! ( fmt, "resume" ) ,
@@ -710,18 +709,11 @@ impl<'tcx> TerminatorKind<'tcx> {
710709 match * self {
711710 Return | Resume | Unreachable => vec ! [ ] ,
712711 Goto { .. } => vec ! [ "" . into( ) ] ,
713- If { .. } => vec ! [ "true" . into( ) , "false" . into( ) ] ,
714- Switch { ref adt_def, .. } => {
715- adt_def. variants
716- . iter ( )
717- . map ( |variant| variant. name . to_string ( ) . into ( ) )
718- . collect ( )
719- }
720712 SwitchInt { ref values, .. } => {
721713 values. iter ( )
722714 . map ( |const_val| {
723715 let mut buf = String :: new ( ) ;
724- fmt_const_val ( & mut buf, const_val) . unwrap ( ) ;
716+ fmt_const_val ( & mut buf, & ConstVal :: Integral ( * const_val) ) . unwrap ( ) ;
725717 buf. into ( )
726718 } )
727719 . chain ( iter:: once ( String :: from ( "otherwise" ) . into ( ) ) )
@@ -997,6 +989,12 @@ pub enum Rvalue<'tcx> {
997989
998990 UnaryOp ( UnOp , Operand < ' tcx > ) ,
999991
992+ /// Read the discriminant of an ADT.
993+ ///
994+ /// Undefined (i.e. no effort is made to make it defined, but there’s no reason why it cannot
995+ /// be defined to return, say, a 0) if ADT is not an enum.
996+ Discriminant ( Lvalue < ' tcx > ) ,
997+
1000998 /// Creates an *uninitialized* Box
1001999 Box ( Ty < ' tcx > ) ,
10021000
@@ -1111,6 +1109,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
11111109 write ! ( fmt, "Checked{:?}({:?}, {:?})" , op, a, b)
11121110 }
11131111 UnaryOp ( ref op, ref a) => write ! ( fmt, "{:?}({:?})" , op, a) ,
1112+ Discriminant ( ref lval) => write ! ( fmt, "discriminant({:?})" , lval) ,
11141113 Box ( ref t) => write ! ( fmt, "Box({:?})" , t) ,
11151114 InlineAsm { ref asm, ref outputs, ref inputs } => {
11161115 write ! ( fmt, "asm!({:?} : {:?} : {:?})" , asm, outputs, inputs)
0 commit comments