Auto merge of #32156 - pnkfelix:borrowck-on-mir-move-analysis, r=nikomatsakis
Move analysis for MIR borrowck This PR adds code for doing MIR-based gathering of the moves in a `fn` and the dataflow to determine where uninitialized locations flow to, analogous to how the same thing is done in `borrowck`. It also adds a couple attributes to print out graphviz visualizations of the analyzed MIR that includes the dataflow analysis results. cc @nikomatsakis
This commit is contained in:
commit
e3f2dfdece
34 changed files with 2014 additions and 136 deletions
|
|
@ -52,7 +52,9 @@ fn replace_newline_with_backslash_l(s: String) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
|
||||
impl<'a, 'ast> dot::Labeller<'a> for LabelledCFG<'a, 'ast> {
|
||||
type Node = Node<'a>;
|
||||
type Edge = Edge<'a>;
|
||||
fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[..]).unwrap() }
|
||||
|
||||
fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> {
|
||||
|
|
@ -97,7 +99,9 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG {
|
||||
impl<'a> dot::GraphWalk<'a> for &'a cfg::CFG {
|
||||
type Node = Node<'a>;
|
||||
type Edge = Edge<'a>;
|
||||
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> {
|
||||
let mut v = Vec::new();
|
||||
self.graph.each_node(|i, nd| { v.push((i, nd)); true });
|
||||
|
|
@ -116,8 +120,10 @@ impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'ast> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast>
|
||||
impl<'a, 'ast> dot::GraphWalk<'a> for LabelledCFG<'a, 'ast>
|
||||
{
|
||||
type Node = Node<'a>;
|
||||
type Edge = Edge<'a>;
|
||||
fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.cfg.nodes() }
|
||||
fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.cfg.edges() }
|
||||
fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { self.cfg.source(edge) }
|
||||
|
|
|
|||
|
|
@ -1017,7 +1017,7 @@ fn check_fn(cx: &mut MatchCheckCtxt,
|
|||
sp: Span,
|
||||
fn_id: NodeId) {
|
||||
match kind {
|
||||
FnKind::Closure => {}
|
||||
FnKind::Closure(_) => {}
|
||||
_ => cx.param_env = ParameterEnvironment::for_item(cx.tcx, fn_id),
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -226,10 +226,10 @@ pub fn lookup_const_fn_by_id<'tcx>(tcx: &TyCtxt<'tcx>, def_id: DefId)
|
|||
};
|
||||
|
||||
match fn_like.kind() {
|
||||
FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _) => {
|
||||
FnKind::ItemFn(_, _, _, hir::Constness::Const, _, _, _) => {
|
||||
Some(fn_like)
|
||||
}
|
||||
FnKind::Method(_, m, _) => {
|
||||
FnKind::Method(_, m, _, _) => {
|
||||
if m.constness == hir::Constness::Const {
|
||||
Some(fn_like)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ fn set_bit(words: &mut [usize], bit: usize) -> bool {
|
|||
let word = bit / usize_bits;
|
||||
let bit_in_word = bit % usize_bits;
|
||||
let bit_mask = 1 << bit_in_word;
|
||||
debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, word);
|
||||
debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
|
||||
let oldv = words[word];
|
||||
let newv = oldv | bit_mask;
|
||||
words[word] = newv;
|
||||
|
|
|
|||
|
|
@ -82,9 +82,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
|
|||
block: &'v hir::Block, span: Span, _: ast::NodeId) {
|
||||
|
||||
let (is_item_fn, is_unsafe_fn) = match fn_kind {
|
||||
FnKind::ItemFn(_, _, unsafety, _, _, _) =>
|
||||
FnKind::ItemFn(_, _, unsafety, _, _, _, _) =>
|
||||
(true, unsafety == hir::Unsafety::Unsafe),
|
||||
FnKind::Method(_, sig, _) =>
|
||||
FnKind::Method(_, sig, _, _) =>
|
||||
(true, sig.unsafety == hir::Unsafety::Unsafe),
|
||||
_ => (false, false),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -173,7 +173,9 @@ impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> {
|
||||
impl<'a, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'tcx> {
|
||||
type Node = Node;
|
||||
type Edge = Edge;
|
||||
fn graph_id(&self) -> dot::Id {
|
||||
dot::Id::new(&*self.graph_name).unwrap()
|
||||
}
|
||||
|
|
@ -224,7 +226,9 @@ fn edge_to_nodes(e: &Edge) -> (Node, Node) {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> dot::GraphWalk<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> {
|
||||
impl<'a, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'tcx> {
|
||||
type Node = Node;
|
||||
type Edge = Edge;
|
||||
fn nodes(&self) -> dot::Nodes<Node> {
|
||||
let mut set = FnvHashSet();
|
||||
for node in self.node_ids.keys() {
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
|
|||
intravisit::walk_fn(self, fk, fd, b, s);
|
||||
self.param_envs.pop();
|
||||
}
|
||||
FnKind::Closure => {
|
||||
FnKind::Closure(..) => {
|
||||
intravisit::walk_fn(self, fk, fd, b, s);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,17 +182,17 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
|
|||
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
|
||||
b: &'v hir::Block, s: Span, fn_id: ast::NodeId) {
|
||||
match fk {
|
||||
FnKind::ItemFn(_, generics, _, _, _, _) => {
|
||||
FnKind::ItemFn(_, generics, _, _, _, _, _) => {
|
||||
self.visit_early_late(subst::FnSpace, generics, |this| {
|
||||
this.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
|
||||
})
|
||||
}
|
||||
FnKind::Method(_, sig, _) => {
|
||||
FnKind::Method(_, sig, _, _) => {
|
||||
self.visit_early_late(subst::FnSpace, &sig.generics, |this| {
|
||||
this.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
|
||||
})
|
||||
}
|
||||
FnKind::Closure => {
|
||||
FnKind::Closure(_) => {
|
||||
self.add_scope_and_walk_fn(fk, fd, b, s, fn_id)
|
||||
}
|
||||
}
|
||||
|
|
@ -471,16 +471,16 @@ impl<'a> LifetimeContext<'a> {
|
|||
fn_id: ast::NodeId) {
|
||||
|
||||
match fk {
|
||||
FnKind::ItemFn(_, generics, _, _, _, _) => {
|
||||
FnKind::ItemFn(_, generics, _, _, _, _, _) => {
|
||||
intravisit::walk_fn_decl(self, fd);
|
||||
self.visit_generics(generics);
|
||||
}
|
||||
FnKind::Method(_, sig, _) => {
|
||||
FnKind::Method(_, sig, _, _) => {
|
||||
intravisit::walk_fn_decl(self, fd);
|
||||
self.visit_generics(&sig.generics);
|
||||
self.visit_explicit_self(&sig.explicit_self);
|
||||
}
|
||||
FnKind::Closure => {
|
||||
FnKind::Closure(_) => {
|
||||
intravisit::walk_fn_decl(self, fd);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue