fn qualify_const(&mut self) -> Qualif {
        debug!("qualifying {} {}", self.mode, self.tcx.item_path_str(self.def_id));

        let mir = self.mir;

        let mut seen_blocks = BitVector::new(mir.basic_blocks().len());
        let mut bb = START_BLOCK;
        loop {
            seen_blocks.insert(bb.index());

            self.visit_basic_block_data(bb, &mir[bb]);

            let target = match mir[bb].terminator().kind {
                TerminatorKind::Goto { target } |
                // Drops are considered noops.
                TerminatorKind::Drop { target, .. } |
                TerminatorKind::Assert { target, .. } |
                TerminatorKind::Call { destination: Some((_, target)), .. } => {
                    Some(target)
                }

                // Non-terminating calls cannot produce any value.
                TerminatorKind::Call { destination: None, .. } => {
                    return Qualif::empty();
                }

                TerminatorKind::If {..} |
                TerminatorKind::Switch {..} |
                TerminatorKind::SwitchInt {..} |
                TerminatorKind::DropAndReplace { .. } |
                TerminatorKind::Resume |
                TerminatorKind::Unreachable => None,

                TerminatorKind::Return => {
                    // Check for unused values. This usually means
                    // there are extra statements in the AST.
                    for temp in mir.temps_iter() {
                        if self.temp_qualif[temp].is_none() {
                            continue;
                        }

                        let state = self.temp_promotion_state[temp];
                        if let TempState::Defined { location, uses: 0 } = state {
                            let data = &mir[location.block];
                            let stmt_idx = location.statement_index;

                            // Get the span for the initialization.
                            let source_info = if stmt_idx < data.statements.len() {
                                data.statements[stmt_idx].source_info
                            } else {
                                data.terminator().source_info
                            };
                            self.span = source_info.span;

                            // Treat this as a statement in the AST.
                            self.statement_like();
                        }
                    }

                    // Make sure there are no extra unassigned variables.
                    self.qualif = Qualif::NOT_CONST;
                    for index in mir.vars_iter() {
                        if !self.const_fn_arg_vars.contains(index.index()) {
                            debug!("unassigned variable {:?}", index);
                            self.assign(&Lvalue::Local(index), Location {
                                block: bb,
                                statement_index: usize::MAX,
                            });
                        }
                    }

                    break;
                }
            };

            match target {
                // No loops allowed.
                Some(target) if !seen_blocks.contains(target.index()) => {
                    bb = target;
                }
                _ => {
                    self.not_const();
                    break;
                }
            }
        }

        let return_ty = mir.return_ty;
        self.qualif = self.return_qualif.unwrap_or(Qualif::NOT_CONST);

        match self.mode {
            Mode::StaticMut => {
                // Check for destructors in static mut.
                self.add_type(return_ty);
                self.deny_drop();
            }
            _ => {
                // Account for errors in consts by using the
                // conservative type qualification instead.
                if self.qualif.intersects(Qualif::CONST_ERROR) {
                    self.qualif = Qualif::empty();
                    self.add_type(return_ty);
                }
            }
        }
        self.qualif
    }
/// Qualify a whole const, static initializer or const fn.
Qualify a whole const, static initializer or const fn.
Qualify a whole const static initializer or const fn .
fn qualify_const(&mut self) -> Qualif {
        debug!("qualifying {} {}", self.mode, self.tcx.item_path_str(self.def_id));
        let mir = self.mir;
        let mut seen_blocks = BitVector::new(mir.basic_blocks().len());
        let mut bb = START_BLOCK;
        loop {
            seen_blocks.insert(bb.index());
            self.visit_basic_block_data(bb, &mir[bb]);
            let target = match mir[bb].terminator().kind {
                TerminatorKind::Goto { target } |
                // Drops are considered noops.
                TerminatorKind::Drop { target, .. } |
                TerminatorKind::Assert { target, .. } |
                TerminatorKind::Call { destination: Some((_, target)), .. } => {
                    Some(target)
                }
                // Non-terminating calls cannot produce any value.
                TerminatorKind::Call { destination: None, .. } => {
                    return Qualif::empty();
                }
                TerminatorKind::If {..} |
                TerminatorKind::Switch {..} |
                TerminatorKind::SwitchInt {..} |
                TerminatorKind::DropAndReplace { .. } |
                TerminatorKind::Resume |
                TerminatorKind::Unreachable => None,
                TerminatorKind::Return => {
                    // Check for unused values. This usually means
                    // there are extra statements in the AST.
                    for temp in mir.temps_iter() {
                        if self.temp_qualif[temp].is_none() {
                            continue;
                        }
                        let state = self.temp_promotion_state[temp];
                        if let TempState::Defined { location, uses: 0 } = state {
                            let data = &mir[location.block];
                            let stmt_idx = location.statement_index;
                            // Get the span for the initialization.
                            let source_info = if stmt_idx < data.statements.len() {
                                data.statements[stmt_idx].source_info
                            } else {
                                data.terminator().source_info
                            };
                            self.span = source_info.span;
                            // Treat this as a statement in the AST.
                            self.statement_like();
                        }
                    }
                    // Make sure there are no extra unassigned variables.
                    self.qualif = Qualif::NOT_CONST;
                    for index in mir.vars_iter() {
                        if !self.const_fn_arg_vars.contains(index.index()) {
                            debug!("unassigned variable {:?}", index);
                            self.assign(&Lvalue::Local(index), Location {
                                block: bb,
                                statement_index: usize::MAX,
                            });
                        }
                    }
                    break;
                }
            };
            match target {
                // No loops allowed.
                Some(target) if !seen_blocks.contains(target.index()) => {
                    bb = target;
                }
                _ => {
                    self.not_const();
                    break;
                }
            }
        }
        let return_ty = mir.return_ty;
        self.qualif = self.return_qualif.unwrap_or(Qualif::NOT_CONST);
        match self.mode {
            Mode::StaticMut => {
                // Check for destructors in static mut.
                self.add_type(return_ty);
                self.deny_drop();
            }
            _ => {
                // Account for errors in consts by using the
                // conservative type qualification instead.
                if self.qualif.intersects(Qualif::CONST_ERROR) {
                    self.qualif = Qualif::empty();
                    self.add_type(return_ty);
                }
            }
        }
        self.qualif
    }
fn qualify_const ( & mut self ) -> Qualif { debug ! ( " " self mode self tcx item_path_str ( self def_id ) ) ; let mir = self . mir ; let mut seen_blocks = BitVector :: new ( mir . basic_blocks ( ) . len ( ) ) ; let mut bb = START_BLOCK ; loop { seen_blocks . insert ( bb . index ( ) ) ; self . visit_basic_block_data ( bb , & mir [ bb ] ) ; let target = match mir [ bb ] . terminator ( ) . kind { TerminatorKind :: Goto { target } | // Drops are considered noops. TerminatorKind :: Drop { target , .. } | TerminatorKind :: Assert { target , .. } | TerminatorKind :: Call { destination : Some ( ( _ , target ) ) , .. } => { Some ( target ) } // Non-terminating calls cannot produce any value. TerminatorKind :: Call { destination : None , .. } => { return Qualif :: empty ( ) ; } TerminatorKind :: If { .. } | TerminatorKind :: Switch { .. } | TerminatorKind :: SwitchInt { .. } | TerminatorKind :: DropAndReplace { .. } | TerminatorKind :: Resume | TerminatorKind :: Unreachable => None , TerminatorKind :: Return => { // Check for unused values. This usually means // there are extra statements in the AST. for temp in mir . temps_iter ( ) { if self . temp_qualif [ temp ] . is_none ( ) { continue ; } let state = self . temp_promotion_state [ temp ] ; if let TempState :: Defined { location , uses : 0 } = state { let data = & mir [ location . block ] ; let stmt_idx = location . statement_index ; // Get the span for the initialization. let source_info = if stmt_idx < data . statements . len ( ) { data . statements [ stmt_idx ] . source_info } else { data . terminator ( ) . source_info } ; self . span = source_info . span ; // Treat this as a statement in the AST. self . statement_like ( ) ; } } // Make sure there are no extra unassigned variables. self . qualif = Qualif :: NOT_CONST ; for index in mir . vars_iter ( ) { if ! self . const_fn_arg_vars . contains ( index . index ( ) ) { debug ! ( " " index ) ; self . assign ( & Lvalue :: Local ( index ) , Location { block : bb , statement_index : usize :: MAX , } ) ; } } break ; } } ; match target { // No loops allowed. Some ( target ) if ! seen_blocks . contains ( target . index ( ) ) => { bb = target ; } _ => { self . not_const ( ) ; break ; } } } let return_ty = mir . return_ty ; self . qualif = self . return_qualif . unwrap_or ( Qualif :: NOT_CONST ) ; match self . mode { Mode :: StaticMut => { // Check for destructors in static mut. self . add_type ( return_ty ) ; self . deny_drop ( ) ; } _ => { // Account for errors in consts by using the // conservative type qualification instead. if self . qualif . intersects ( Qualif :: CONST_ERROR ) { self . qualif = Qualif :: empty ( ) ; self . add_type ( return_ty ) ; } } } self . qualif }
Qualify a whole const, static initializer or const fn.
Qualify a whole const static initializer or const fn .
&mut self
&mut self