about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2017-11-24 13:00:09 +0100
committerFelix S. Klock II <pnkfelix@pnkfx.org>2017-12-13 00:15:17 -0600
commit93c4ffe72f8e406a166e258c80723606cd7d8304 (patch)
treeabbdb5b22d7fa0a56c6a6d658a8be58129e9c0ea
parent691f022767aa5dec36635ab17bb767d5a80407db (diff)
downloadrust-93c4ffe72f8e406a166e258c80723606cd7d8304.tar.gz
rust-93c4ffe72f8e406a166e258c80723606cd7d8304.zip
Revised graphviz rendering API to avoid requiring borrowed state.
Made `do_dataflow` and related API `pub(crate)`.
-rw-r--r--src/librustc_mir/borrow_check/mod.rs12
-rw-r--r--src/librustc_mir/dataflow/graphviz.rs10
-rw-r--r--src/librustc_mir/dataflow/mod.rs45
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs20
-rw-r--r--src/librustc_mir/transform/generator.rs6
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs8
6 files changed, 60 insertions, 41 deletions
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 128052e5894..8bfb5fee9f6 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -28,7 +28,7 @@ use rustc_data_structures::indexed_vec::Idx;
 use syntax::ast;
 use syntax_pos::Span;
 
-use dataflow::do_dataflow;
+use dataflow::{do_dataflow, DebugFormatted};
 use dataflow::MoveDataParamEnv;
 use dataflow::DataflowResultsConsumer;
 use dataflow::{FlowAtLocation, FlowsAtLocation};
@@ -157,7 +157,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         &attributes,
         &dead_unwinds,
         MaybeInitializedLvals::new(tcx, mir, &mdpe),
-        |bd, i| &bd.move_data().move_paths[i],
+        |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
     ));
     let flow_uninits = FlowAtLocation::new(do_dataflow(
         tcx,
@@ -166,7 +166,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         &attributes,
         &dead_unwinds,
         MaybeUninitializedLvals::new(tcx, mir, &mdpe),
-        |bd, i| &bd.move_data().move_paths[i],
+        |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
     ));
     let flow_move_outs = FlowAtLocation::new(do_dataflow(
         tcx,
@@ -175,7 +175,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         &attributes,
         &dead_unwinds,
         MovingOutStatements::new(tcx, mir, &mdpe),
-        |bd, i| &bd.move_data().moves[i],
+        |bd, i| DebugFormatted::new(&bd.move_data().moves[i]),
     ));
     let flow_ever_inits = FlowAtLocation::new(do_dataflow(
         tcx,
@@ -184,7 +184,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         &attributes,
         &dead_unwinds,
         EverInitializedLvals::new(tcx, mir, &mdpe),
-        |bd, i| &bd.move_data().inits[i],
+        |bd, i| DebugFormatted::new(&bd.move_data().inits[i]),
     ));
 
     // If we are in non-lexical mode, compute the non-lexical lifetimes.
@@ -212,7 +212,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         &attributes,
         &dead_unwinds,
         Borrows::new(tcx, mir, opt_regioncx, def_id, body_id),
-        |bd, i| bd.location(i),
+        |bd, i| DebugFormatted::new(bd.location(i)),
     ));
 
     let mut state = Flows::new(
diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs
index 7ff4fbcf199..b79e044b24f 100644
--- a/src/librustc_mir/dataflow/graphviz.rs
+++ b/src/librustc_mir/dataflow/graphviz.rs
@@ -18,7 +18,6 @@ use rustc_data_structures::indexed_vec::Idx;
 use dot;
 use dot::IntoCow;
 
-use std::fmt::Debug;
 use std::fs::File;
 use std::io;
 use std::io::prelude::*;
@@ -29,6 +28,7 @@ use util;
 
 use super::{BitDenotation, DataflowState};
 use super::DataflowBuilder;
+use super::DebugFormatted;
 
 pub trait MirWithFlowState<'tcx> {
     type BD: BitDenotation;
@@ -60,9 +60,9 @@ pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
     render_idx: P)
     -> io::Result<()>
     where BD: BitDenotation,
-          P: Fn(&BD, BD::Idx) -> &Debug
+          P: Fn(&BD, BD::Idx) -> DebugFormatted
 {
-    let g = Graph { mbcx: mbcx, phantom: PhantomData, render_idx: render_idx };
+    let g = Graph { mbcx, phantom: PhantomData, render_idx };
     let mut v = Vec::new();
     dot::render(&g, &mut v)?;
     debug!("print_borrowck_graph_to path: {} node_id: {}",
@@ -82,7 +82,7 @@ fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec<Edge> {
 
 impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
     where MWF: MirWithFlowState<'tcx>,
-          P: for <'b> Fn(&'b MWF::BD, <MWF::BD as BitDenotation>::Idx) -> &'b Debug,
+          P: Fn(&MWF::BD, <MWF::BD as BitDenotation>::Idx) -> DebugFormatted,
 {
     type Node = Node;
     type Edge = Edge;
@@ -142,7 +142,7 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
         const ALIGN_RIGHT: &'static str = r#"align="right""#;
         const FACE_MONOSPACE: &'static str = r#"FACE="Courier""#;
         fn chunked_present_left<W:io::Write>(w: &mut W,
-                                             interpreted: &[&Debug],
+                                             interpreted: &[DebugFormatted],
                                              chunk_size: usize)
                                              -> io::Result<()>
         {
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 2136b41e462..8624cbbf50a 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -19,7 +19,7 @@ use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Ter
 use rustc::session::Session;
 
 use std::borrow::Borrow;
-use std::fmt::{self, Debug};
+use std::fmt;
 use std::io;
 use std::mem;
 use std::path::PathBuf;
@@ -51,10 +51,29 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation
     print_postflow_to: Option<String>,
 }
 
-pub trait Dataflow<BD: BitDenotation> {
+/// `DebugFormatted` encapsulates the "{:?}" rendering of some
+/// arbitrary value. This way: you pay cost of allocating an extra
+/// string (as well as that of rendering up-front); in exchange, you
+/// don't have to hand over ownership of your value or deal with
+/// borrowing it.
+pub(crate) struct DebugFormatted(String);
+
+impl DebugFormatted {
+    pub fn new(input: &fmt::Debug) -> DebugFormatted {
+        DebugFormatted(format!("{:?}", input))
+    }
+}
+
+impl fmt::Debug for DebugFormatted {
+    fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+        write!(w, "{}", self.0)
+    }
+}
+
+pub(crate) trait Dataflow<BD: BitDenotation> {
     /// Sets up and runs the dataflow problem, using `p` to render results if
     /// implementation so chooses.
-    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
+    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> DebugFormatted {
         let _ = p; // default implementation does not instrument process.
         self.build_sets();
         self.propagate();
@@ -69,7 +88,7 @@ pub trait Dataflow<BD: BitDenotation> {
 
 impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation
 {
-    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug {
+    fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> DebugFormatted {
         self.flow_state.build_sets();
         self.pre_dataflow_instrumentation(|c,i| p(c,i)).unwrap();
         self.flow_state.propagate();
@@ -109,7 +128,7 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                                  p: P)
                                                  -> DataflowResults<BD>
     where BD: BitDenotation,
-          P: Fn(&BD, BD::Idx) -> &fmt::Debug
+          P: Fn(&BD, BD::Idx) -> DebugFormatted
 {
     let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> {
         if let Some(item) = has_rustc_mir_with(attrs, name) {
@@ -231,7 +250,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
 impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation
 {
     fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
-        where P: Fn(&BD, BD::Idx) -> &Debug
+        where P: Fn(&BD, BD::Idx) -> DebugFormatted
     {
         if let Some(ref path_str) = self.print_preflow_to {
             let path = dataflow_path(BD::name(), "preflow", path_str);
@@ -242,7 +261,7 @@ impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation
     }
 
     fn post_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
-        where P: Fn(&BD, BD::Idx) -> &Debug
+        where P: Fn(&BD, BD::Idx) -> DebugFormatted
     {
         if let Some(ref path_str) = self.print_postflow_to {
             let path = dataflow_path(BD::name(), "postflow", path_str);
@@ -403,12 +422,12 @@ impl<O: BitDenotation> DataflowState<O> {
         words.each_bit(bits_per_block, f)
     }
 
-    pub fn interpret_set<'c, P>(&self,
-                                o: &'c O,
-                                words: &IdxSet<O::Idx>,
-                                render_idx: &P)
-                                -> Vec<&'c Debug>
-        where P: Fn(&O, O::Idx) -> &Debug
+    pub(crate) fn interpret_set<'c, P>(&self,
+                                       o: &'c O,
+                                       words: &IdxSet<O::Idx>,
+                                       render_idx: &P)
+                                       -> Vec<DebugFormatted>
+        where P: Fn(&O, O::Idx) -> DebugFormatted
     {
         let mut v = Vec::new();
         self.each_bit(words, |i| {
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index b075d2637da..106bc39d0fc 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -14,7 +14,7 @@ use dataflow::{DataflowResults};
 use dataflow::{on_all_children_bits, on_all_drop_children_bits};
 use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits};
 use dataflow::MoveDataParamEnv;
-use dataflow;
+use dataflow::{self, do_dataflow, DebugFormatted};
 use rustc::hir;
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
@@ -59,13 +59,13 @@ impl MirPass for ElaborateDrops {
             };
             let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env);
             let flow_inits =
-                dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
-                                      MaybeInitializedLvals::new(tcx, mir, &env),
-                                      |bd, p| &bd.move_data().move_paths[p]);
+                do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+                            MaybeInitializedLvals::new(tcx, mir, &env),
+                            |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
             let flow_uninits =
-                dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
-                                      MaybeUninitializedLvals::new(tcx, mir, &env),
-                                      |bd, p| &bd.move_data().move_paths[p]);
+                do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+                            MaybeUninitializedLvals::new(tcx, mir, &env),
+                            |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
 
             ElaborateDropsCtxt {
                 tcx,
@@ -96,9 +96,9 @@ fn find_dead_unwinds<'a, 'tcx>(
     // reach cleanup blocks, which can't have unwind edges themselves.
     let mut dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
     let flow_inits =
-        dataflow::do_dataflow(tcx, mir, id, &[], &dead_unwinds,
-                           MaybeInitializedLvals::new(tcx, mir, &env),
-                           |bd, p| &bd.move_data().move_paths[p]);
+        do_dataflow(tcx, mir, id, &[], &dead_unwinds,
+                    MaybeInitializedLvals::new(tcx, mir, &env),
+                    |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p]));
     for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
         let location = match bb_data.terminator().kind {
             TerminatorKind::Drop { ref location, unwind: Some(_), .. } |
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index aaa28634eb8..455a07c04cf 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -78,7 +78,7 @@ use std::mem;
 use transform::{MirPass, MirSource};
 use transform::simplify;
 use transform::no_landing_pads::no_landing_pads;
-use dataflow::{self, MaybeStorageLive, state_for_location};
+use dataflow::{do_dataflow, DebugFormatted, MaybeStorageLive, state_for_location};
 
 pub struct StateTransform;
 
@@ -341,8 +341,8 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
     let analysis = MaybeStorageLive::new(mir);
     let storage_live =
-        dataflow::do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis,
-                              |bd, p| &bd.mir().local_decls[p]);
+        do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis,
+                    |bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
 
     let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.local_decls.len()));
     ignored.visit_mir(mir);
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 08508143976..6b8e2b073cc 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -18,7 +18,7 @@ use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
 use transform::{MirPass, MirSource};
 
-use dataflow::do_dataflow;
+use dataflow::{do_dataflow, DebugFormatted};
 use dataflow::MoveDataParamEnv;
 use dataflow::BitDenotation;
 use dataflow::DataflowResults;
@@ -51,15 +51,15 @@ impl MirPass for SanityCheck {
         let flow_inits =
             do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
                         MaybeInitializedLvals::new(tcx, mir, &mdpe),
-                        |bd, i| &bd.move_data().move_paths[i]);
+                        |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
         let flow_uninits =
             do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
                         MaybeUninitializedLvals::new(tcx, mir, &mdpe),
-                        |bd, i| &bd.move_data().move_paths[i]);
+                        |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
         let flow_def_inits =
             do_dataflow(tcx, mir, id, &attributes, &dead_unwinds,
                         DefinitelyInitializedLvals::new(tcx, mir, &mdpe),
-                        |bd, i| &bd.move_data().move_paths[i]);
+                        |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]));
 
         if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() {
             sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits);