-
-
Save lqd/7e178cb9ac8302e24272965048627f21 to your computer and use it in GitHub Desktop.
librustc_mir/borrow_check/mod.rs with stats about MirVisitors' `super_mir` calls in different "regions" of `do_mir_borrowck`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fn mir_borrowck<'a, 'tcx>( | |
tcx: TyCtxt<'a, 'tcx, 'tcx>, | |
def_id: DefId, | |
) -> BorrowCheckResult<'tcx> { | |
// called 1883 times in clap, indirectly recursive (w/ depth of 4) | |
// generating 11777 "super_mir" calls out of 31005 total | |
let input_mir = tcx.mir_validated(def_id); | |
debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); | |
if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir_borrowck() { | |
return BorrowCheckResult { | |
closure_requirements: None, | |
used_mut_upvars: SmallVec::new(), | |
}; | |
} | |
let opt_closure_req = tcx.infer_ctxt().enter(|infcx| { | |
let input_mir: &Mir = &input_mir.borrow(); | |
do_mir_borrowck(&infcx, input_mir, def_id) | |
}); | |
debug!("mir_borrowck done"); | |
opt_closure_req | |
} | |
fn do_mir_borrowck<'a, 'gcx, 'tcx>( | |
infcx: &InferCtxt<'a, 'gcx, 'tcx>, | |
input_mir: &Mir<'gcx>, | |
def_id: DefId, | |
) -> BorrowCheckResult<'gcx> { | |
let tcx = infcx.tcx; | |
let attributes = tcx.get_attrs(def_id); | |
let param_env = tcx.param_env(def_id); | |
let id = tcx.hir | |
.as_local_node_id(def_id) | |
.expect("do_mir_borrowck: non-local DefId"); | |
// region 1 start | |
// Replace all regions with fresh inference variables. This | |
// requires first making our own copy of the MIR. This copy will | |
// be modified (in place) to contain non-lexical lifetimes. It | |
// will have a lifetime tied to the inference context. | |
let mut mir: Mir<'tcx> = input_mir.clone(); | |
let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut mir); | |
let mir = &mir; // no further changes | |
let location_table = &LocationTable::new(mir); | |
// region 1 end - generating 1883 "super_mir" calls out of 11777 (per depth 0 to 4: 1580/266/22/14/1) | |
// region 2 start | |
let move_data: MoveData<'tcx> = match MoveData::gather_moves(mir, tcx) { | |
Ok(move_data) => move_data, | |
Err((move_data, move_errors)) => { | |
for move_error in move_errors { | |
let (span, kind): (Span, IllegalMoveOriginKind) = match move_error { | |
MoveError::UnionMove { .. } => { | |
unimplemented!("don't know how to report union move errors yet.") | |
} | |
MoveError::IllegalMove { | |
cannot_move_out_of: o, | |
} => (o.span, o.kind), | |
}; | |
let origin = Origin::Mir; | |
let mut err = match kind { | |
IllegalMoveOriginKind::Static => { | |
tcx.cannot_move_out_of(span, "static item", origin) | |
} | |
IllegalMoveOriginKind::BorrowedContent { target_ty: ty } => { | |
// Inspect the type of the content behind the | |
// borrow to provide feedback about why this | |
// was a move rather than a copy. | |
match ty.sty { | |
ty::TyArray(..) | ty::TySlice(..) => | |
tcx.cannot_move_out_of_interior_noncopy(span, ty, None, origin), | |
_ => tcx.cannot_move_out_of(span, "borrowed content", origin) | |
} | |
} | |
IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => { | |
tcx.cannot_move_out_of_interior_of_drop(span, ty, origin) | |
} | |
IllegalMoveOriginKind::InteriorOfSliceOrArray { ty, is_index } => { | |
tcx.cannot_move_out_of_interior_noncopy(span, ty, Some(is_index), origin) | |
} | |
}; | |
err.emit(); | |
} | |
move_data | |
} | |
}; | |
// region 2 end - generating 0 "super_mir" calls out of 11777 | |
// region 3 start | |
let mdpe = MoveDataParamEnv { | |
move_data: move_data, | |
param_env: param_env, | |
}; | |
let body_id = match tcx.def_key(def_id).disambiguated_data.data { | |
DefPathData::StructCtor | DefPathData::EnumVariant(_) => None, | |
_ => Some(tcx.hir.body_owned_by(id)), | |
}; | |
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); | |
let mut flow_inits = FlowAtLocation::new(do_dataflow( | |
tcx, | |
mir, | |
id, | |
&attributes, | |
&dead_unwinds, | |
MaybeInitializedPlaces::new(tcx, mir, &mdpe), | |
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), | |
)); | |
let flow_uninits = FlowAtLocation::new(do_dataflow( | |
tcx, | |
mir, | |
id, | |
&attributes, | |
&dead_unwinds, | |
MaybeUninitializedPlaces::new(tcx, mir, &mdpe), | |
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]), | |
)); | |
let flow_move_outs = FlowAtLocation::new(do_dataflow( | |
tcx, | |
mir, | |
id, | |
&attributes, | |
&dead_unwinds, | |
MovingOutStatements::new(tcx, mir, &mdpe), | |
|bd, i| DebugFormatted::new(&bd.move_data().moves[i]), | |
)); | |
let flow_ever_inits = FlowAtLocation::new(do_dataflow( | |
tcx, | |
mir, | |
id, | |
&attributes, | |
&dead_unwinds, | |
EverInitializedPlaces::new(tcx, mir, &mdpe), | |
|bd, i| DebugFormatted::new(&bd.move_data().inits[i]), | |
)); | |
// region 3 end - generating 0 "super_mir" calls out of 11777 | |
// region 4 start | |
let borrow_set = Rc::new(BorrowSet::build(tcx, mir)); | |
// If we are in non-lexical mode, compute the non-lexical lifetimes. | |
let (regioncx, polonius_output, opt_closure_req) = nll::compute_regions( | |
infcx, | |
def_id, | |
free_regions, | |
mir, | |
location_table, | |
param_env, | |
&mut flow_inits, | |
&mdpe.move_data, | |
&borrow_set, | |
); | |
let regioncx = Rc::new(regioncx); | |
let flow_inits = flow_inits; // remove mut | |
// region 4 end - generating 1883 "super_mir" calls out of 11777 (per depth 0 to 4: 1580/266/22/14/1) | |
// region 5 start | |
let flow_borrows = FlowAtLocation::new(do_dataflow( | |
tcx, | |
mir, | |
id, | |
&attributes, | |
&dead_unwinds, | |
Borrows::new(tcx, mir, regioncx.clone(), def_id, body_id, &borrow_set), | |
|rs, i| DebugFormatted::new(&rs.location(i)), | |
)); | |
let movable_generator = match tcx.hir.get(id) { | |
hir::map::Node::NodeExpr(&hir::Expr { | |
node: hir::ExprClosure(.., Some(hir::GeneratorMovability::Static)), | |
.. | |
}) => false, | |
_ => true, | |
}; | |
// region 5 end - generating 0 "super_mir" calls out of 11777 | |
// region 6 start | |
let dominators = mir.dominators(); | |
// region 6 end - generating 0 "super_mir" calls out of 11777 | |
// region 7 start | |
let mut mbcx = MirBorrowckCtxt { | |
tcx: tcx, | |
mir: mir, | |
mir_def_id: def_id, | |
move_data: &mdpe.move_data, | |
param_env: param_env, | |
movable_generator, | |
locals_are_invalidated_at_exit: match tcx.hir.body_owner_kind(id) { | |
hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false, | |
hir::BodyOwnerKind::Fn => true, | |
}, | |
access_place_error_reported: FxHashSet(), | |
reservation_error_reported: FxHashSet(), | |
moved_error_reported: FxHashSet(), | |
nonlexical_regioncx: regioncx, | |
used_mut: FxHashSet(), | |
used_mut_upvars: SmallVec::new(), | |
borrow_set, | |
dominators, | |
}; | |
let mut state = Flows::new( | |
flow_borrows, | |
flow_inits, | |
flow_uninits, | |
flow_move_outs, | |
flow_ever_inits, | |
polonius_output, | |
); | |
// region 7 end - generating 0 "super_mir" calls out of 11777 | |
// region 8 start | |
mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer | |
// For each non-user used mutable variable, check if it's been assigned from | |
// a user-declared local. If so, then put that local into the used_mut set. | |
// Note that this set is expected to be small - only upvars from closures | |
// would have a chance of erroneously adding non-user-defined mutable vars | |
// to the set. | |
let temporary_used_locals: FxHashSet<Local> = | |
mbcx.used_mut.iter() | |
.filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable) | |
.cloned() | |
.collect(); | |
// region 8 end - generating 0 "super_mir" calls out of 11777 | |
// region 9 start | |
for local in temporary_used_locals { | |
let assignments = mbcx.mir.find_assignments(local); | |
for location in assignments { | |
for moi in &mbcx.move_data.loc_map[location] { | |
let mpi = &mbcx.move_data.moves[*moi].path; | |
let path = &mbcx.move_data.move_paths[*mpi]; | |
debug!("assignment of {:?} to {:?}, adding {:?} to used mutable set", | |
path.place, local, path.place); | |
if let Place::Local(user_local) = path.place { | |
mbcx.used_mut.insert(user_local); | |
} | |
} | |
} | |
} | |
// region 9 end - generating 8011 "super_mir" calls out of 11777 (per depth 0 to 4: 7966/31/13/0/0) | |
// region 10 start | |
debug!("mbcx.used_mut: {:?}", mbcx.used_mut); | |
for local in mbcx.mir.mut_vars_and_args_iter().filter(|local| !mbcx.used_mut.contains(local)) { | |
if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.source_scope_local_data { | |
let local_decl = &mbcx.mir.local_decls[local]; | |
// Skip implicit `self` argument for closures | |
if local.index() == 1 && tcx.is_closure(mbcx.mir_def_id) { | |
continue; | |
} | |
// Skip over locals that begin with an underscore or have no name | |
match local_decl.name { | |
Some(name) => if name.as_str().starts_with("_") { continue; }, | |
None => continue, | |
} | |
let span = local_decl.source_info.span; | |
let mut_span = tcx.sess.codemap().span_until_non_whitespace(span); | |
tcx.struct_span_lint_node( | |
UNUSED_MUT, | |
vsi[local_decl.source_info.scope].lint_root, | |
span, | |
"variable does not need to be mutable" | |
) | |
.span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()) | |
.emit(); | |
} | |
} | |
// region 10 end - generating 0 "super_mir" calls out of 11777 | |
BorrowCheckResult { | |
closure_requirements: opt_closure_req, | |
used_mut_upvars: mbcx.used_mut_upvars, | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment