Skip to content

Commit e3f2dfd

Browse files
committed
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
2 parents c7bdfd4 + 782c0cf commit e3f2dfd

File tree

34 files changed

+2014
-136
lines changed

34 files changed

+2014
-136
lines changed

mk/crates.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml rustc_front\
9797
log graphviz rustc_llvm rustc_back rustc_data_structures\
9898
rustc_const_eval
9999
DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
100-
DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
100+
DEPS_rustc_borrowck := rustc rustc_front rustc_mir log graphviz syntax
101101
DEPS_rustc_data_structures := std log serialize
102102
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
103103
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \

src/libgraphviz/lib.rs

+63-39
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,19 @@
6262
//! dot::render(&edges, output).unwrap()
6363
//! }
6464
//!
65-
//! impl<'a> dot::Labeller<'a, Nd, Ed> for Edges {
65+
//! impl<'a> dot::Labeller<'a> for Edges {
66+
//! type Node = Nd;
67+
//! type Edge = Ed;
6668
//! fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example1").unwrap() }
6769
//!
6870
//! fn node_id(&'a self, n: &Nd) -> dot::Id<'a> {
6971
//! dot::Id::new(format!("N{}", *n)).unwrap()
7072
//! }
7173
//! }
7274
//!
73-
//! impl<'a> dot::GraphWalk<'a, Nd, Ed> for Edges {
75+
//! impl<'a> dot::GraphWalk<'a> for Edges {
76+
//! type Node = Nd;
77+
//! type Edge = Ed;
7478
//! fn nodes(&self) -> dot::Nodes<'a,Nd> {
7579
//! // (assumes that |N| \approxeq |E|)
7680
//! let &Edges(ref v) = self;
@@ -167,7 +171,9 @@
167171
//! dot::render(&graph, output).unwrap()
168172
//! }
169173
//!
170-
//! impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph {
174+
//! impl<'a> dot::Labeller<'a> for Graph {
175+
//! type Node = Nd;
176+
//! type Edge = Ed<'a>;
171177
//! fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example2").unwrap() }
172178
//! fn node_id(&'a self, n: &Nd) -> dot::Id<'a> {
173179
//! dot::Id::new(format!("N{}", n)).unwrap()
@@ -180,7 +186,9 @@
180186
//! }
181187
//! }
182188
//!
183-
//! impl<'a> dot::GraphWalk<'a, Nd, Ed<'a>> for Graph {
189+
//! impl<'a> dot::GraphWalk<'a> for Graph {
190+
//! type Node = Nd;
191+
//! type Edge = Ed<'a>;
184192
//! fn nodes(&self) -> dot::Nodes<'a,Nd> { (0..self.nodes.len()).collect() }
185193
//! fn edges(&'a self) -> dot::Edges<'a,Ed<'a>> { self.edges.iter().collect() }
186194
//! fn source(&self, e: &Ed) -> Nd { let & &(s,_) = e; s }
@@ -225,7 +233,9 @@
225233
//! dot::render(&graph, output).unwrap()
226234
//! }
227235
//!
228-
//! impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph {
236+
//! impl<'a> dot::Labeller<'a> for Graph {
237+
//! type Node = Nd<'a>;
238+
//! type Edge = Ed<'a>;
229239
//! fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3").unwrap() }
230240
//! fn node_id(&'a self, n: &Nd<'a>) -> dot::Id<'a> {
231241
//! dot::Id::new(format!("N{}", n.0)).unwrap()
@@ -239,7 +249,9 @@
239249
//! }
240250
//! }
241251
//!
242-
//! impl<'a> dot::GraphWalk<'a, Nd<'a>, Ed<'a>> for Graph {
252+
//! impl<'a> dot::GraphWalk<'a> for Graph {
253+
//! type Node = Nd<'a>;
254+
//! type Edge = Ed<'a>;
243255
//! fn nodes(&'a self) -> dot::Nodes<'a,Nd<'a>> {
244256
//! self.nodes.iter().map(|s| &s[..]).enumerate().collect()
245257
//! }
@@ -447,45 +459,48 @@ impl<'a> Id<'a> {
447459
/// The graph instance is responsible for providing the DOT compatible
448460
/// identifiers for the nodes and (optionally) rendered labels for the nodes and
449461
/// edges, as well as an identifier for the graph itself.
450-
pub trait Labeller<'a,N,E> {
462+
pub trait Labeller<'a> {
463+
type Node;
464+
type Edge;
465+
451466
/// Must return a DOT compatible identifier naming the graph.
452467
fn graph_id(&'a self) -> Id<'a>;
453468

454469
/// Maps `n` to a unique identifier with respect to `self`. The
455470
/// implementor is responsible for ensuring that the returned name
456471
/// is a valid DOT identifier.
457-
fn node_id(&'a self, n: &N) -> Id<'a>;
472+
fn node_id(&'a self, n: &Self::Node) -> Id<'a>;
458473

459474
/// Maps `n` to one of the [graphviz `shape` names][1]. If `None`
460475
/// is returned, no `shape` attribute is specified.
461476
///
462477
/// [1]: http://www.graphviz.org/content/node-shapes
463-
fn node_shape(&'a self, _node: &N) -> Option<LabelText<'a>> {
478+
fn node_shape(&'a self, _node: &Self::Node) -> Option<LabelText<'a>> {
464479
None
465480
}
466481

467482
/// Maps `n` to a label that will be used in the rendered output.
468483
/// The label need not be unique, and may be the empty string; the
469484
/// default is just the output from `node_id`.
470-
fn node_label(&'a self, n: &N) -> LabelText<'a> {
485+
fn node_label(&'a self, n: &Self::Node) -> LabelText<'a> {
471486
LabelStr(self.node_id(n).name)
472487
}
473488

474489
/// Maps `e` to a label that will be used in the rendered output.
475490
/// The label need not be unique, and may be the empty string; the
476491
/// default is in fact the empty string.
477-
fn edge_label(&'a self, e: &E) -> LabelText<'a> {
492+
fn edge_label(&'a self, e: &Self::Edge) -> LabelText<'a> {
478493
let _ignored = e;
479494
LabelStr("".into_cow())
480495
}
481496

482497
/// Maps `n` to a style that will be used in the rendered output.
483-
fn node_style(&'a self, _n: &N) -> Style {
498+
fn node_style(&'a self, _n: &Self::Node) -> Style {
484499
Style::None
485500
}
486501

487502
/// Maps `e` to a style that will be used in the rendered output.
488-
fn edge_style(&'a self, _e: &E) -> Style {
503+
fn edge_style(&'a self, _e: &Self::Edge) -> Style {
489504
Style::None
490505
}
491506
}
@@ -596,15 +611,18 @@ pub type Edges<'a,E> = Cow<'a,[E]>;
596611
/// `Cow<[T]>` to leave implementors the freedom to create
597612
/// entirely new vectors or to pass back slices into internally owned
598613
/// vectors.
599-
pub trait GraphWalk<'a, N: Clone, E: Clone> {
614+
pub trait GraphWalk<'a> {
615+
type Node: Clone;
616+
type Edge: Clone;
617+
600618
/// Returns all the nodes in this graph.
601-
fn nodes(&'a self) -> Nodes<'a, N>;
619+
fn nodes(&'a self) -> Nodes<'a, Self::Node>;
602620
/// Returns all of the edges in this graph.
603-
fn edges(&'a self) -> Edges<'a, E>;
621+
fn edges(&'a self) -> Edges<'a, Self::Edge>;
604622
/// The source node for `edge`.
605-
fn source(&'a self, edge: &E) -> N;
623+
fn source(&'a self, edge: &Self::Edge) -> Self::Node;
606624
/// The target node for `edge`.
607-
fn target(&'a self, edge: &E) -> N;
625+
fn target(&'a self, edge: &Self::Edge) -> Self::Node;
608626
}
609627

610628
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
@@ -622,28 +640,26 @@ pub fn default_options() -> Vec<RenderOption> {
622640

623641
/// Renders directed graph `g` into the writer `w` in DOT syntax.
624642
/// (Simple wrapper around `render_opts` that passes a default set of options.)
625-
pub fn render<'a,
626-
N: Clone + 'a,
627-
E: Clone + 'a,
628-
G: Labeller<'a, N, E> + GraphWalk<'a, N, E>,
629-
W: Write>
630-
(g: &'a G,
631-
w: &mut W)
632-
-> io::Result<()> {
643+
pub fn render<'a,N,E,G,W>(g: &'a G, w: &mut W) -> io::Result<()>
644+
where N: Clone + 'a,
645+
E: Clone + 'a,
646+
G: Labeller<'a, Node=N, Edge=E> + GraphWalk<'a, Node=N, Edge=E>,
647+
W: Write
648+
{
633649
render_opts(g, w, &[])
634650
}
635651

636652
/// Renders directed graph `g` into the writer `w` in DOT syntax.
637653
/// (Main entry point for the library.)
638-
pub fn render_opts<'a,
639-
N: Clone + 'a,
640-
E: Clone + 'a,
641-
G: Labeller<'a, N, E> + GraphWalk<'a, N, E>,
642-
W: Write>
643-
(g: &'a G,
644-
w: &mut W,
645-
options: &[RenderOption])
646-
-> io::Result<()> {
654+
pub fn render_opts<'a, N, E, G, W>(g: &'a G,
655+
w: &mut W,
656+
options: &[RenderOption])
657+
-> io::Result<()>
658+
where N: Clone + 'a,
659+
E: Clone + 'a,
660+
G: Labeller<'a, Node=N, Edge=E> + GraphWalk<'a, Node=N, Edge=E>,
661+
W: Write
662+
{
647663
fn writeln<W: Write>(w: &mut W, arg: &[&str]) -> io::Result<()> {
648664
for &s in arg {
649665
try!(w.write_all(s.as_bytes()));
@@ -858,7 +874,9 @@ mod tests {
858874
Id::new(format!("N{}", *n)).unwrap()
859875
}
860876

861-
impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraph {
877+
impl<'a> Labeller<'a> for LabelledGraph {
878+
type Node = Node;
879+
type Edge = &'a Edge;
862880
fn graph_id(&'a self) -> Id<'a> {
863881
Id::new(&self.name[..]).unwrap()
864882
}
@@ -882,7 +900,9 @@ mod tests {
882900
}
883901
}
884902

885-
impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraphWithEscStrs {
903+
impl<'a> Labeller<'a> for LabelledGraphWithEscStrs {
904+
type Node = Node;
905+
type Edge = &'a Edge;
886906
fn graph_id(&'a self) -> Id<'a> {
887907
self.graph.graph_id()
888908
}
@@ -901,7 +921,9 @@ mod tests {
901921
}
902922
}
903923

904-
impl<'a> GraphWalk<'a, Node, &'a Edge> for LabelledGraph {
924+
impl<'a> GraphWalk<'a> for LabelledGraph {
925+
type Node = Node;
926+
type Edge = &'a Edge;
905927
fn nodes(&'a self) -> Nodes<'a, Node> {
906928
(0..self.node_labels.len()).collect()
907929
}
@@ -916,7 +938,9 @@ mod tests {
916938
}
917939
}
918940

919-
impl<'a> GraphWalk<'a, Node, &'a Edge> for LabelledGraphWithEscStrs {
941+
impl<'a> GraphWalk<'a> for LabelledGraphWithEscStrs {
942+
type Node = Node;
943+
type Edge = &'a Edge;
920944
fn nodes(&'a self) -> Nodes<'a, Node> {
921945
self.graph.nodes()
922946
}

src/librustc/front/map/blocks.rs

+28-19
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ pub use self::Code::*;
2626
use front::map::{self, Node};
2727
use syntax::abi;
2828
use rustc_front::hir::{Block, FnDecl};
29-
use syntax::ast::{Name, NodeId};
29+
use syntax::ast::{Attribute, Name, NodeId};
30+
use syntax::attr::ThinAttributesExt;
3031
use rustc_front::hir as ast;
3132
use syntax::codemap::Span;
3233
use rustc_front::intravisit::FnKind;
@@ -116,7 +117,8 @@ struct ItemFnParts<'a> {
116117
generics: &'a ast::Generics,
117118
body: &'a Block,
118119
id: NodeId,
119-
span: Span
120+
span: Span,
121+
attrs: &'a [Attribute],
120122
}
121123

122124
/// These are all the components one can extract from a closure expr
@@ -125,12 +127,13 @@ struct ClosureParts<'a> {
125127
decl: &'a FnDecl,
126128
body: &'a Block,
127129
id: NodeId,
128-
span: Span
130+
span: Span,
131+
attrs: &'a [Attribute],
129132
}
130133

131134
impl<'a> ClosureParts<'a> {
132-
fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span) -> ClosureParts<'a> {
133-
ClosureParts { decl: d, body: b, id: id, span: s }
135+
fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
136+
ClosureParts { decl: d, body: b, id: id, span: s, attrs: attrs }
134137
}
135138
}
136139

@@ -165,37 +168,37 @@ impl<'a> FnLikeNode<'a> {
165168

166169
pub fn body(self) -> &'a Block {
167170
self.handle(|i: ItemFnParts<'a>| &*i.body,
168-
|_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _| body,
171+
|_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _, _| body,
169172
|c: ClosureParts<'a>| c.body)
170173
}
171174

172175
pub fn decl(self) -> &'a FnDecl {
173176
self.handle(|i: ItemFnParts<'a>| &*i.decl,
174-
|_, _, sig: &'a ast::MethodSig, _, _, _| &sig.decl,
177+
|_, _, sig: &'a ast::MethodSig, _, _, _, _| &sig.decl,
175178
|c: ClosureParts<'a>| c.decl)
176179
}
177180

178181
pub fn span(self) -> Span {
179182
self.handle(|i: ItemFnParts| i.span,
180-
|_, _, _: &'a ast::MethodSig, _, _, span| span,
183+
|_, _, _: &'a ast::MethodSig, _, _, span, _| span,
181184
|c: ClosureParts| c.span)
182185
}
183186

184187
pub fn id(self) -> NodeId {
185188
self.handle(|i: ItemFnParts| i.id,
186-
|id, _, _: &'a ast::MethodSig, _, _, _| id,
189+
|id, _, _: &'a ast::MethodSig, _, _, _, _| id,
187190
|c: ClosureParts| c.id)
188191
}
189192

190193
pub fn kind(self) -> FnKind<'a> {
191194
let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
192-
FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis)
195+
FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis, p.attrs)
193196
};
194-
let closure = |_: ClosureParts| {
195-
FnKind::Closure
197+
let closure = |c: ClosureParts<'a>| {
198+
FnKind::Closure(c.attrs)
196199
};
197-
let method = |_, name: Name, sig: &'a ast::MethodSig, vis, _, _| {
198-
FnKind::Method(name, sig, vis)
200+
let method = |_, name: Name, sig: &'a ast::MethodSig, vis, _, _, attrs| {
201+
FnKind::Method(name, sig, vis, attrs)
199202
};
200203
self.handle(item, method, closure)
201204
}
@@ -207,7 +210,8 @@ impl<'a> FnLikeNode<'a> {
207210
&'a ast::MethodSig,
208211
Option<ast::Visibility>,
209212
&'a ast::Block,
210-
Span)
213+
Span,
214+
&'a [Attribute])
211215
-> A,
212216
C: FnOnce(ClosureParts<'a>) -> A,
213217
{
@@ -224,20 +228,21 @@ impl<'a> FnLikeNode<'a> {
224228
abi: abi,
225229
vis: i.vis,
226230
constness: constness,
227-
span: i.span
231+
span: i.span,
232+
attrs: &i.attrs,
228233
}),
229234
_ => panic!("item FnLikeNode that is not fn-like"),
230235
},
231236
map::NodeTraitItem(ti) => match ti.node {
232237
ast::MethodTraitItem(ref sig, Some(ref body)) => {
233-
method(ti.id, ti.name, sig, None, body, ti.span)
238+
method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs)
234239
}
235240
_ => panic!("trait method FnLikeNode that is not fn-like"),
236241
},
237242
map::NodeImplItem(ii) => {
238243
match ii.node {
239244
ast::ImplItemKind::Method(ref sig, ref body) => {
240-
method(ii.id, ii.name, sig, Some(ii.vis), body, ii.span)
245+
method(ii.id, ii.name, sig, Some(ii.vis), body, ii.span, &ii.attrs)
241246
}
242247
_ => {
243248
panic!("impl method FnLikeNode that is not fn-like")
@@ -246,7 +251,11 @@ impl<'a> FnLikeNode<'a> {
246251
}
247252
map::NodeExpr(e) => match e.node {
248253
ast::ExprClosure(_, ref decl, ref block) =>
249-
closure(ClosureParts::new(&decl, &block, e.id, e.span)),
254+
closure(ClosureParts::new(&decl,
255+
&block,
256+
e.id,
257+
e.span,
258+
e.attrs.as_attr_slice())),
250259
_ => panic!("expr FnLikeNode that is not fn-like"),
251260
},
252261
_ => panic!("other FnLikeNode that is not fn-like"),

0 commit comments

Comments
 (0)