@@ -83,7 +83,7 @@ should go to.
8383*/
8484
8585use crate :: build:: { BlockAnd , BlockAndExtension , BlockFrame , Builder , CFG } ;
86- use crate :: hair:: { ExprRef , LintLevel } ;
86+ use crate :: hair:: { Expr , ExprRef , LintLevel } ;
8787use rustc:: middle:: region;
8888use rustc:: ty:: Ty ;
8989use rustc:: hir;
@@ -829,6 +829,78 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
829829
830830 // Other
831831 // =====
832+ /// Branch based on a boolean condition.
833+ ///
834+ /// This is a special case because the temporary for the condition needs to
835+ /// be dropped on both the true and the false arm.
836+ pub fn test_bool (
837+ & mut self ,
838+ mut block : BasicBlock ,
839+ condition : Expr < ' tcx > ,
840+ source_info : SourceInfo ,
841+ ) -> ( BasicBlock , BasicBlock ) {
842+ let cond = unpack ! ( block = self . as_local_operand( block, condition) ) ;
843+ let true_block = self . cfg . start_new_block ( ) ;
844+ let false_block = self . cfg . start_new_block ( ) ;
845+ let term = TerminatorKind :: if_ (
846+ self . hir . tcx ( ) ,
847+ cond. clone ( ) ,
848+ true_block,
849+ false_block,
850+ ) ;
851+ self . cfg . terminate ( block, source_info, term) ;
852+
853+ match cond {
854+ // Don't try to drop a constant
855+ Operand :: Constant ( _) => ( ) ,
856+ // If constants and statics, we don't generate StorageLive for this
857+ // temporary, so don't try to generate StorageDead for it either.
858+ _ if self . local_scope ( ) . is_none ( ) => ( ) ,
859+ Operand :: Copy ( Place :: Base ( PlaceBase :: Local ( cond_temp) ) )
860+ | Operand :: Move ( Place :: Base ( PlaceBase :: Local ( cond_temp) ) ) => {
861+ // Manually drop the condition on both branches.
862+ let top_scope = self . scopes . scopes . last_mut ( ) . unwrap ( ) ;
863+ let top_drop_data = top_scope. drops . pop ( ) . unwrap ( ) ;
864+
865+ match top_drop_data. kind {
866+ DropKind :: Value { .. } => {
867+ bug ! ( "Drop scheduled on top of condition variable" )
868+ }
869+ DropKind :: Storage => {
870+ // Drop the storage for both value and storage drops.
871+ // Only temps and vars need their storage dead.
872+ match top_drop_data. location {
873+ Place :: Base ( PlaceBase :: Local ( index) ) => {
874+ let source_info = top_scope. source_info ( top_drop_data. span ) ;
875+ assert_eq ! ( index, cond_temp, "Drop scheduled on top of condition" ) ;
876+ self . cfg . push (
877+ true_block,
878+ Statement {
879+ source_info,
880+ kind : StatementKind :: StorageDead ( index)
881+ } ,
882+ ) ;
883+ self . cfg . push (
884+ false_block,
885+ Statement {
886+ source_info,
887+ kind : StatementKind :: StorageDead ( index)
888+ } ,
889+ ) ;
890+ }
891+ _ => unreachable ! ( ) ,
892+ }
893+ }
894+ }
895+
896+ top_scope. invalidate_cache ( true , self . is_generator , true ) ;
897+ }
898+ _ => bug ! ( "Expected as_local_operand to produce a temporary" ) ,
899+ }
900+
901+ ( true_block, false_block)
902+ }
903+
832904 /// Creates a path that performs all required cleanup for unwinding.
833905 ///
834906 /// This path terminates in Resume. Returns the start of the path.
@@ -942,57 +1014,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9421014 top_scope. drops . clear ( ) ;
9431015 top_scope. invalidate_cache ( false , self . is_generator , true ) ;
9441016 }
945-
946- /// Drops the single variable provided
947- ///
948- /// * The scope must be the top scope.
949- /// * The variable must be in that scope.
950- /// * The variable must be at the top of that scope: it's the next thing
951- /// scheduled to drop.
952- /// * The drop must be of `DropKind::Storage`.
953- ///
954- /// This is used for the boolean holding the result of the match guard. We
955- /// do this because:
956- ///
957- /// * The boolean is different for each pattern
958- /// * There is only one exit for the arm scope
959- /// * The guard expression scope is too short, it ends just before the
960- /// boolean is tested.
961- pub ( crate ) fn pop_variable (
962- & mut self ,
963- block : BasicBlock ,
964- region_scope : region:: Scope ,
965- variable : Local ,
966- ) {
967- let top_scope = self . scopes . scopes . last_mut ( ) . unwrap ( ) ;
968-
969- assert_eq ! ( top_scope. region_scope, region_scope) ;
970-
971- let top_drop_data = top_scope. drops . pop ( ) . unwrap ( ) ;
972-
973- match top_drop_data. kind {
974- DropKind :: Value { .. } => {
975- bug ! ( "Should not be calling pop_top_variable on non-copy type!" )
976- }
977- DropKind :: Storage => {
978- // Drop the storage for both value and storage drops.
979- // Only temps and vars need their storage dead.
980- match top_drop_data. location {
981- Place :: Base ( PlaceBase :: Local ( index) ) => {
982- let source_info = top_scope. source_info ( top_drop_data. span ) ;
983- assert_eq ! ( index, variable) ;
984- self . cfg . push ( block, Statement {
985- source_info,
986- kind : StatementKind :: StorageDead ( index)
987- } ) ;
988- }
989- _ => unreachable ! ( ) ,
990- }
991- }
992- }
993-
994- top_scope. invalidate_cache ( true , self . is_generator , true ) ;
995- }
9961017}
9971018
9981019/// Builds drops for pop_scope and exit_scope.
0 commit comments