fn promote_temp(&mut self, temp: Temp) -> Temp {
        let old_keep_original = self.keep_original;
        let (bb, stmt_idx) = match self.temps[temp] {
            TempState::Defined {
                location: Location { block, statement_index },
                uses
            } if uses > 0 => {
                if uses > 1 {
                    self.keep_original = true;
                }
                (block, statement_index)
            }
            state =>  {
                span_bug!(self.promoted.span, "{:?} not promotable: {:?}",
                          temp, state);
            }
        };
        if !self.keep_original {
            self.temps[temp] = TempState::PromotedOut;
        }

        let no_stmts = self.source[bb].statements.len();

        // First, take the Rvalue or Call out of the source MIR,
        // or duplicate it, depending on keep_original.
        let (mut rvalue, mut call) = (None, None);
        let source_info = if stmt_idx < no_stmts {
            let statement = &mut self.source[bb].statements[stmt_idx];
            let StatementKind::Assign(_, ref mut rhs) = statement.kind;
            if self.keep_original {
                rvalue = Some(rhs.clone());
            } else {
                let unit = Rvalue::Aggregate(AggregateKind::Tuple, vec![]);
                rvalue = Some(mem::replace(rhs, unit));
            }
            statement.source_info
        } else if self.keep_original {
            let terminator = self.source[bb].terminator().clone();
            call = Some(terminator.kind);
            terminator.source_info
        } else {
            let terminator = self.source[bb].terminator_mut();
            let target = match terminator.kind {
                TerminatorKind::Call {
                    destination: ref mut dest @ Some(_),
                    ref mut cleanup, ..
                } => {
                    // No cleanup necessary.
                    cleanup.take();

                    // We'll put a new destination in later.
                    dest.take().unwrap().1
                }
                ref kind => {
                    span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
                }
            };
            call = Some(mem::replace(&mut terminator.kind, TerminatorKind::Goto {
                target: target
            }));
            terminator.source_info
        };

        // Then, recurse for components in the Rvalue or Call.
        if stmt_idx < no_stmts {
            self.visit_rvalue(rvalue.as_mut().unwrap());
        } else {
            self.visit_terminator_kind(bb, call.as_mut().unwrap());
        }

        let new_temp = self.promoted.temp_decls.push(TempDecl {
            ty: self.source.temp_decls[temp].ty
        });

        // Inject the Rvalue or Call into the promoted MIR.
        if stmt_idx < no_stmts {
            self.assign(Lvalue::Temp(new_temp), rvalue.unwrap(), source_info.span);
        } else {
            let last = self.promoted.basic_blocks().last().unwrap();
            let new_target = self.new_block();
            let mut call = call.unwrap();
            match call {
                TerminatorKind::Call { ref mut destination, ..}  => {
                    *destination = Some((Lvalue::Temp(new_temp), new_target));
                }
                _ => bug!()
            }
            let terminator = self.promoted[last].terminator_mut();
            terminator.source_info.span = source_info.span;
            terminator.kind = call;
        }

        // Restore the old duplication state.
        self.keep_original = old_keep_original;

        new_temp
    }
/// Copy the initialization of this temp to the
/// promoted MIR, recursing through temps.
Copy the initialization of this temp to the
promoted MIR, recursing through temps.
Copy the initialization of this temp to the promoted MIR recursing through temps .
fn promote_temp(&mut self, temp: Temp) -> Temp {
        let old_keep_original = self.keep_original;
        let (bb, stmt_idx) = match self.temps[temp] {
            TempState::Defined {
                location: Location { block, statement_index },
                uses
            } if uses > 0 => {
                if uses > 1 {
                    self.keep_original = true;
                }
                (block, statement_index)
            }
            state =>  {
                span_bug!(self.promoted.span, "{:?} not promotable: {:?}",
                          temp, state);
            }
        };
        if !self.keep_original {
            self.temps[temp] = TempState::PromotedOut;
        }
        let no_stmts = self.source[bb].statements.len();
        // First, take the Rvalue or Call out of the source MIR,
        // or duplicate it, depending on keep_original.
        let (mut rvalue, mut call) = (None, None);
        let source_info = if stmt_idx < no_stmts {
            let statement = &mut self.source[bb].statements[stmt_idx];
            let StatementKind::Assign(_, ref mut rhs) = statement.kind;
            if self.keep_original {
                rvalue = Some(rhs.clone());
            } else {
                let unit = Rvalue::Aggregate(AggregateKind::Tuple, vec![]);
                rvalue = Some(mem::replace(rhs, unit));
            }
            statement.source_info
        } else if self.keep_original {
            let terminator = self.source[bb].terminator().clone();
            call = Some(terminator.kind);
            terminator.source_info
        } else {
            let terminator = self.source[bb].terminator_mut();
            let target = match terminator.kind {
                TerminatorKind::Call {
                    destination: ref mut dest @ Some(_),
                    ref mut cleanup, ..
                } => {
                    // No cleanup necessary.
                    cleanup.take();
                    // We'll put a new destination in later.
                    dest.take().unwrap().1
                }
                ref kind => {
                    span_bug!(terminator.source_info.span, "{:?} not promotable", kind);
                }
            };
            call = Some(mem::replace(&mut terminator.kind, TerminatorKind::Goto {
                target: target
            }));
            terminator.source_info
        };
        // Then, recurse for components in the Rvalue or Call.
        if stmt_idx < no_stmts {
            self.visit_rvalue(rvalue.as_mut().unwrap());
        } else {
            self.visit_terminator_kind(bb, call.as_mut().unwrap());
        }
        let new_temp = self.promoted.temp_decls.push(TempDecl {
            ty: self.source.temp_decls[temp].ty
        });
        // Inject the Rvalue or Call into the promoted MIR.
        if stmt_idx < no_stmts {
            self.assign(Lvalue::Temp(new_temp), rvalue.unwrap(), source_info.span);
        } else {
            let last = self.promoted.basic_blocks().last().unwrap();
            let new_target = self.new_block();
            let mut call = call.unwrap();
            match call {
                TerminatorKind::Call { ref mut destination, ..}  => {
                    *destination = Some((Lvalue::Temp(new_temp), new_target));
                }
                _ => bug!()
            }
            let terminator = self.promoted[last].terminator_mut();
            terminator.source_info.span = source_info.span;
            terminator.kind = call;
        }
        // Restore the old duplication state.
        self.keep_original = old_keep_original;
        new_temp
    }
fn promote_temp ( & mut self , temp : Temp ) -> Temp { let old_keep_original = self . keep_original ; let ( bb , stmt_idx ) = match self . temps [ temp ] { TempState :: Defined { location : Location { block , statement_index } , uses } if uses > 0 => { if uses > 1 { self . keep_original = true ; } ( block , statement_index ) } state => { span_bug ! ( self promoted span " " temp state ) ; } } ; if ! self . keep_original { self . temps [ temp ] = TempState :: PromotedOut ; } let no_stmts = self . source [ bb ] . statements . len ( ) ; // First, take the Rvalue or Call out of the source MIR, // or duplicate it, depending on keep_original. let ( mut rvalue , mut call ) = ( None , None ) ; let source_info = if stmt_idx < no_stmts { let statement = & mut self . source [ bb ] . statements [ stmt_idx ] ; let StatementKind :: Assign ( _ , ref mut rhs ) = statement . kind ; if self . keep_original { rvalue = Some ( rhs . clone ( ) ) ; } else { let unit = Rvalue :: Aggregate ( AggregateKind :: Tuple , vec ! [ ] ) ; rvalue = Some ( mem :: replace ( rhs , unit ) ) ; } statement . source_info } else if self . keep_original { let terminator = self . source [ bb ] . terminator ( ) . clone ( ) ; call = Some ( terminator . kind ) ; terminator . source_info } else { let terminator = self . source [ bb ] . terminator_mut ( ) ; let target = match terminator . kind { TerminatorKind :: Call { destination : ref mut dest @ Some ( _ ) , ref mut cleanup , .. } => { // No cleanup necessary. cleanup . take ( ) ; // We'll put a new destination in later. dest . take ( ) . unwrap ( ) . 1 } ref kind => { span_bug ! ( terminator source_info span " " kind ) ; } } ; call = Some ( mem :: replace ( & mut terminator . kind , TerminatorKind :: Goto { target : target } ) ) ; terminator . source_info } ; // Then, recurse for components in the Rvalue or Call. if stmt_idx < no_stmts { self . visit_rvalue ( rvalue . as_mut ( ) . unwrap ( ) ) ; } else { self . visit_terminator_kind ( bb , call . as_mut ( ) . unwrap ( ) ) ; } let new_temp = self . promoted . temp_decls . push ( TempDecl { ty : self . source . temp_decls [ temp ] . ty } ) ; // Inject the Rvalue or Call into the promoted MIR. if stmt_idx < no_stmts { self . assign ( Lvalue :: Temp ( new_temp ) , rvalue . unwrap ( ) , source_info . span ) ; } else { let last = self . promoted . basic_blocks ( ) . last ( ) . unwrap ( ) ; let new_target = self . new_block ( ) ; let mut call = call . unwrap ( ) ; match call { TerminatorKind :: Call { ref mut destination , .. } => { * destination = Some ( ( Lvalue :: Temp ( new_temp ) , new_target ) ) ; } _ => bug ! ( ) } let terminator = self . promoted [ last ] . terminator_mut ( ) ; terminator . source_info . span = source_info . span ; terminator . kind = call ; } // Restore the old duplication state. self . keep_original = old_keep_original ; new_temp }
Copy the initialization of this temp to the
promoted MIR, recursing through temps.
Copy the initialization of this temp to the promoted MIR recursing through temps .
&mut self
temp
Temp
&mut self
temp
Temp