Skip to content

Allow MIR borrowck to catch unused mutable locals #48605

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 29, 2018
5 changes: 5 additions & 0 deletions src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,11 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Literal<'gcx> {

impl_stable_hash_for!(struct mir::Location { block, statement_index });

impl_stable_hash_for!(struct mir::BorrowCheckResult<'tcx> {
closure_requirements,
used_mut_upvars
});

impl_stable_hash_for!(struct mir::ClosureRegionRequirements<'tcx> {
num_external_vids,
outlives_requirements
Expand Down
23 changes: 23 additions & 0 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators};
use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors};
use rustc_data_structures::control_flow_graph::ControlFlowGraph;
use rustc_data_structures::small_vec::SmallVec;
use rustc_serialize as serialize;
use hir::def::CtorKind;
use hir::def_id::DefId;
Expand Down Expand Up @@ -247,6 +248,22 @@ impl<'tcx> Mir<'tcx> {
})
}

/// Returns an iterator over all user-declared mutable arguments and locals.
#[inline]
pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item=Local> + 'a {
(1..self.local_decls.len()).filter_map(move |index| {
let local = Local::new(index);
let decl = &self.local_decls[local];
if (decl.is_user_variable || index < self.arg_count + 1)
&& decl.mutability == Mutability::Mut
{
Some(local)
} else {
None
}
})
}

/// Returns an iterator over all function arguments.
#[inline]
pub fn args_iter(&self) -> impl Iterator<Item=Local> {
Expand Down Expand Up @@ -2029,6 +2046,12 @@ pub struct GeneratorLayout<'tcx> {
pub fields: Vec<LocalDecl<'tcx>>,
}

#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BorrowCheckResult<'gcx> {
pub closure_requirements: Option<ClosureRegionRequirements<'gcx>>,
pub used_mut_upvars: SmallVec<[Field; 8]>,
}

/// After we borrow check a closure, we are left with various
/// requirements that we have inferred between the free regions that
/// appear in the closure's signature or on its field types. These
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/maps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ define_maps! { <'tcx>

/// Borrow checks the function body. If this is a closure, returns
/// additional requirements that the closure's creator must verify.
[] fn mir_borrowck: MirBorrowCheck(DefId) -> Option<mir::ClosureRegionRequirements<'tcx>>,
[] fn mir_borrowck: MirBorrowCheck(DefId) -> mir::BorrowCheckResult<'tcx>,

/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_borrowck/borrowck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
{
check_loans::check_loans(&mut bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
}
unused::check(&mut bccx, body);

if !tcx.use_mir_borrowck() {
unused::check(&mut bccx, body);
}

Lrc::new(BorrowCheckResult {
used_mut_nodes: bccx.used_mut_nodes.into_inner(),
Expand Down
Loading