Skip to content
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

Move analysis for MIR borrowck #32156

Merged
merged 11 commits into from
Mar 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ DEPS_rustc := syntax fmt_macros flate arena serialize getopts rbml rustc_front\
log graphviz rustc_llvm rustc_back rustc_data_structures\
rustc_const_eval
DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
DEPS_rustc_borrowck := rustc rustc_front rustc_mir log graphviz syntax
DEPS_rustc_data_structures := std log serialize
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
Expand Down
102 changes: 63 additions & 39 deletions src/libgraphviz/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,19 @@
//! dot::render(&edges, output).unwrap()
//! }
//!
//! impl<'a> dot::Labeller<'a, Nd, Ed> for Edges {
//! impl<'a> dot::Labeller<'a> for Edges {
//! type Node = Nd;
//! type Edge = Ed;
//! fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example1").unwrap() }
//!
//! fn node_id(&'a self, n: &Nd) -> dot::Id<'a> {
//! dot::Id::new(format!("N{}", *n)).unwrap()
//! }
//! }
//!
//! impl<'a> dot::GraphWalk<'a, Nd, Ed> for Edges {
//! impl<'a> dot::GraphWalk<'a> for Edges {
//! type Node = Nd;
//! type Edge = Ed;
//! fn nodes(&self) -> dot::Nodes<'a,Nd> {
//! // (assumes that |N| \approxeq |E|)
//! let &Edges(ref v) = self;
Expand Down Expand Up @@ -167,7 +171,9 @@
//! dot::render(&graph, output).unwrap()
//! }
//!
//! impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph {
//! impl<'a> dot::Labeller<'a> for Graph {
//! type Node = Nd;
//! type Edge = Ed<'a>;
//! fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example2").unwrap() }
//! fn node_id(&'a self, n: &Nd) -> dot::Id<'a> {
//! dot::Id::new(format!("N{}", n)).unwrap()
Expand All @@ -180,7 +186,9 @@
//! }
//! }
//!
//! impl<'a> dot::GraphWalk<'a, Nd, Ed<'a>> for Graph {
//! impl<'a> dot::GraphWalk<'a> for Graph {
//! type Node = Nd;
//! type Edge = Ed<'a>;
//! fn nodes(&self) -> dot::Nodes<'a,Nd> { (0..self.nodes.len()).collect() }
//! fn edges(&'a self) -> dot::Edges<'a,Ed<'a>> { self.edges.iter().collect() }
//! fn source(&self, e: &Ed) -> Nd { let & &(s,_) = e; s }
Expand Down Expand Up @@ -225,7 +233,9 @@
//! dot::render(&graph, output).unwrap()
//! }
//!
//! impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph {
//! impl<'a> dot::Labeller<'a> for Graph {
//! type Node = Nd<'a>;
//! type Edge = Ed<'a>;
//! fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3").unwrap() }
//! fn node_id(&'a self, n: &Nd<'a>) -> dot::Id<'a> {
//! dot::Id::new(format!("N{}", n.0)).unwrap()
Expand All @@ -239,7 +249,9 @@
//! }
//! }
//!
//! impl<'a> dot::GraphWalk<'a, Nd<'a>, Ed<'a>> for Graph {
//! impl<'a> dot::GraphWalk<'a> for Graph {
//! type Node = Nd<'a>;
//! type Edge = Ed<'a>;
//! fn nodes(&'a self) -> dot::Nodes<'a,Nd<'a>> {
//! self.nodes.iter().map(|s| &s[..]).enumerate().collect()
//! }
Expand Down Expand Up @@ -447,45 +459,48 @@ impl<'a> Id<'a> {
/// The graph instance is responsible for providing the DOT compatible
/// identifiers for the nodes and (optionally) rendered labels for the nodes and
/// edges, as well as an identifier for the graph itself.
pub trait Labeller<'a,N,E> {
pub trait Labeller<'a> {
type Node;
type Edge;

/// Must return a DOT compatible identifier naming the graph.
fn graph_id(&'a self) -> Id<'a>;

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

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

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

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

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

/// Maps `e` to a style that will be used in the rendered output.
fn edge_style(&'a self, _e: &E) -> Style {
fn edge_style(&'a self, _e: &Self::Edge) -> Style {
Style::None
}
}
Expand Down Expand Up @@ -596,15 +611,18 @@ pub type Edges<'a,E> = Cow<'a,[E]>;
/// `Cow<[T]>` to leave implementors the freedom to create
/// entirely new vectors or to pass back slices into internally owned
/// vectors.
pub trait GraphWalk<'a, N: Clone, E: Clone> {
pub trait GraphWalk<'a> {
type Node: Clone;
type Edge: Clone;

/// Returns all the nodes in this graph.
fn nodes(&'a self) -> Nodes<'a, N>;
fn nodes(&'a self) -> Nodes<'a, Self::Node>;
/// Returns all of the edges in this graph.
fn edges(&'a self) -> Edges<'a, E>;
fn edges(&'a self) -> Edges<'a, Self::Edge>;
/// The source node for `edge`.
fn source(&'a self, edge: &E) -> N;
fn source(&'a self, edge: &Self::Edge) -> Self::Node;
/// The target node for `edge`.
fn target(&'a self, edge: &E) -> N;
fn target(&'a self, edge: &Self::Edge) -> Self::Node;
}

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

/// Renders directed graph `g` into the writer `w` in DOT syntax.
/// (Simple wrapper around `render_opts` that passes a default set of options.)
pub fn render<'a,
N: Clone + 'a,
E: Clone + 'a,
G: Labeller<'a, N, E> + GraphWalk<'a, N, E>,
W: Write>
(g: &'a G,
w: &mut W)
-> io::Result<()> {
pub fn render<'a,N,E,G,W>(g: &'a G, w: &mut W) -> io::Result<()>
where N: Clone + 'a,
E: Clone + 'a,
G: Labeller<'a, Node=N, Edge=E> + GraphWalk<'a, Node=N, Edge=E>,
W: Write
{
render_opts(g, w, &[])
}

/// Renders directed graph `g` into the writer `w` in DOT syntax.
/// (Main entry point for the library.)
pub fn render_opts<'a,
N: Clone + 'a,
E: Clone + 'a,
G: Labeller<'a, N, E> + GraphWalk<'a, N, E>,
W: Write>
(g: &'a G,
w: &mut W,
options: &[RenderOption])
-> io::Result<()> {
pub fn render_opts<'a, N, E, G, W>(g: &'a G,
w: &mut W,
options: &[RenderOption])
-> io::Result<()>
where N: Clone + 'a,
E: Clone + 'a,
G: Labeller<'a, Node=N, Edge=E> + GraphWalk<'a, Node=N, Edge=E>,
W: Write
{
fn writeln<W: Write>(w: &mut W, arg: &[&str]) -> io::Result<()> {
for &s in arg {
try!(w.write_all(s.as_bytes()));
Expand Down Expand Up @@ -858,7 +874,9 @@ mod tests {
Id::new(format!("N{}", *n)).unwrap()
}

impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraph {
impl<'a> Labeller<'a> for LabelledGraph {
type Node = Node;
type Edge = &'a Edge;
fn graph_id(&'a self) -> Id<'a> {
Id::new(&self.name[..]).unwrap()
}
Expand All @@ -882,7 +900,9 @@ mod tests {
}
}

impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraphWithEscStrs {
impl<'a> Labeller<'a> for LabelledGraphWithEscStrs {
type Node = Node;
type Edge = &'a Edge;
fn graph_id(&'a self) -> Id<'a> {
self.graph.graph_id()
}
Expand All @@ -901,7 +921,9 @@ mod tests {
}
}

impl<'a> GraphWalk<'a, Node, &'a Edge> for LabelledGraph {
impl<'a> GraphWalk<'a> for LabelledGraph {
type Node = Node;
type Edge = &'a Edge;
fn nodes(&'a self) -> Nodes<'a, Node> {
(0..self.node_labels.len()).collect()
}
Expand All @@ -916,7 +938,9 @@ mod tests {
}
}

impl<'a> GraphWalk<'a, Node, &'a Edge> for LabelledGraphWithEscStrs {
impl<'a> GraphWalk<'a> for LabelledGraphWithEscStrs {
type Node = Node;
type Edge = &'a Edge;
fn nodes(&'a self) -> Nodes<'a, Node> {
self.graph.nodes()
}
Expand Down
47 changes: 28 additions & 19 deletions src/librustc/front/map/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ pub use self::Code::*;
use front::map::{self, Node};
use syntax::abi;
use rustc_front::hir::{Block, FnDecl};
use syntax::ast::{Name, NodeId};
use syntax::ast::{Attribute, Name, NodeId};
use syntax::attr::ThinAttributesExt;
use rustc_front::hir as ast;
use syntax::codemap::Span;
use rustc_front::intravisit::FnKind;
Expand Down Expand Up @@ -116,7 +117,8 @@ struct ItemFnParts<'a> {
generics: &'a ast::Generics,
body: &'a Block,
id: NodeId,
span: Span
span: Span,
attrs: &'a [Attribute],
}

/// These are all the components one can extract from a closure expr
Expand All @@ -125,12 +127,13 @@ struct ClosureParts<'a> {
decl: &'a FnDecl,
body: &'a Block,
id: NodeId,
span: Span
span: Span,
attrs: &'a [Attribute],
}

impl<'a> ClosureParts<'a> {
fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span) -> ClosureParts<'a> {
ClosureParts { decl: d, body: b, id: id, span: s }
fn new(d: &'a FnDecl, b: &'a Block, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self {
ClosureParts { decl: d, body: b, id: id, span: s, attrs: attrs }
}
}

Expand Down Expand Up @@ -165,37 +168,37 @@ impl<'a> FnLikeNode<'a> {

pub fn body(self) -> &'a Block {
self.handle(|i: ItemFnParts<'a>| &*i.body,
|_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _| body,
|_, _, _: &'a ast::MethodSig, _, body: &'a ast::Block, _, _| body,
|c: ClosureParts<'a>| c.body)
}

pub fn decl(self) -> &'a FnDecl {
self.handle(|i: ItemFnParts<'a>| &*i.decl,
|_, _, sig: &'a ast::MethodSig, _, _, _| &sig.decl,
|_, _, sig: &'a ast::MethodSig, _, _, _, _| &sig.decl,
|c: ClosureParts<'a>| c.decl)
}

pub fn span(self) -> Span {
self.handle(|i: ItemFnParts| i.span,
|_, _, _: &'a ast::MethodSig, _, _, span| span,
|_, _, _: &'a ast::MethodSig, _, _, span, _| span,
|c: ClosureParts| c.span)
}

pub fn id(self) -> NodeId {
self.handle(|i: ItemFnParts| i.id,
|id, _, _: &'a ast::MethodSig, _, _, _| id,
|id, _, _: &'a ast::MethodSig, _, _, _, _| id,
|c: ClosureParts| c.id)
}

pub fn kind(self) -> FnKind<'a> {
let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis)
FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis, p.attrs)
};
let closure = |_: ClosureParts| {
FnKind::Closure
let closure = |c: ClosureParts<'a>| {
FnKind::Closure(c.attrs)
};
let method = |_, name: Name, sig: &'a ast::MethodSig, vis, _, _| {
FnKind::Method(name, sig, vis)
let method = |_, name: Name, sig: &'a ast::MethodSig, vis, _, _, attrs| {
FnKind::Method(name, sig, vis, attrs)
};
self.handle(item, method, closure)
}
Expand All @@ -207,7 +210,8 @@ impl<'a> FnLikeNode<'a> {
&'a ast::MethodSig,
Option<ast::Visibility>,
&'a ast::Block,
Span)
Span,
&'a [Attribute])
-> A,
C: FnOnce(ClosureParts<'a>) -> A,
{
Expand All @@ -224,20 +228,21 @@ impl<'a> FnLikeNode<'a> {
abi: abi,
vis: i.vis,
constness: constness,
span: i.span
span: i.span,
attrs: &i.attrs,
}),
_ => panic!("item FnLikeNode that is not fn-like"),
},
map::NodeTraitItem(ti) => match ti.node {
ast::MethodTraitItem(ref sig, Some(ref body)) => {
method(ti.id, ti.name, sig, None, body, ti.span)
method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs)
}
_ => panic!("trait method FnLikeNode that is not fn-like"),
},
map::NodeImplItem(ii) => {
match ii.node {
ast::ImplItemKind::Method(ref sig, ref body) => {
method(ii.id, ii.name, sig, Some(ii.vis), body, ii.span)
method(ii.id, ii.name, sig, Some(ii.vis), body, ii.span, &ii.attrs)
}
_ => {
panic!("impl method FnLikeNode that is not fn-like")
Expand All @@ -246,7 +251,11 @@ impl<'a> FnLikeNode<'a> {
}
map::NodeExpr(e) => match e.node {
ast::ExprClosure(_, ref decl, ref block) =>
closure(ClosureParts::new(&decl, &block, e.id, e.span)),
closure(ClosureParts::new(&decl,
&block,
e.id,
e.span,
e.attrs.as_attr_slice())),
_ => panic!("expr FnLikeNode that is not fn-like"),
},
_ => panic!("other FnLikeNode that is not fn-like"),
Expand Down
Loading