From 1ec99179c1ccb4305354d2d4ee503c40adcd714d Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 20 Jan 2020 15:05:26 -0800 Subject: [PATCH] Add an `into_engine` method to `Analysis` This makes it more ergonomic to create a dataflow engine and obviates the need to pick between `new_gen_kill` and `new_generic`. --- src/librustc_mir/dataflow/generic/mod.rs | 30 +++++++++++++++++++ .../transform/check_consts/validation.rs | 9 +++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/mod.rs b/src/librustc_mir/dataflow/generic/mod.rs index c9b4f875ebdf..ed742143150f 100644 --- a/src/librustc_mir/dataflow/generic/mod.rs +++ b/src/librustc_mir/dataflow/generic/mod.rs @@ -35,6 +35,8 @@ use std::io; use rustc::mir::{self, BasicBlock, Location}; +use rustc::ty::TyCtxt; +use rustc_hir::def_id::DefId; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_index::vec::{Idx, IndexVec}; @@ -166,6 +168,22 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { args: &[mir::Operand<'tcx>], return_place: &mir::Place<'tcx>, ); + + /// Creates an `Engine` to find the fixpoint for this dataflow problem. + /// + /// This is functionally equivalent to calling the appropriate `Engine` constructor. It should + /// not be overridden. Its purpose is to allow consumers of this API to use method-chaining. + fn into_engine( + self, + tcx: TyCtxt<'tcx>, + body: &'mir mir::Body<'tcx>, + def_id: DefId, + ) -> Engine<'mir, 'tcx, Self> + where + Self: Sized, + { + Engine::new_generic(tcx, body, def_id, self) + } } /// A gen/kill dataflow problem. @@ -272,6 +290,18 @@ where ) { self.call_return_effect(state, block, func, args, return_place); } + + fn into_engine( + self, + tcx: TyCtxt<'tcx>, + body: &'mir mir::Body<'tcx>, + def_id: DefId, + ) -> Engine<'mir, 'tcx, Self> + where + Self: Sized, + { + Engine::new_gen_kill(tcx, body, def_id, self) + } } /// The legal operations for a transfer function in a gen/kill problem. diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 35107a31aa12..aad471c785ac 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -22,6 +22,7 @@ use super::resolver::FlowSensitiveAnalysis; use super::{is_lang_panic_fn, ConstKind, Item, Qualif}; use crate::const_eval::{is_const_fn, is_unstable_const_fn}; use crate::dataflow::{self as old_dataflow, generic as dataflow}; +use dataflow::Analysis; pub type IndirectlyMutableResults<'mir, 'tcx> = old_dataflow::DataflowResultsCursor<'mir, 'tcx, IndirectlyMutableLocals<'mir, 'tcx>>; @@ -33,10 +34,10 @@ struct QualifCursor<'a, 'mir, 'tcx, Q: Qualif> { impl QualifCursor<'a, 'mir, 'tcx, Q> { pub fn new(q: Q, item: &'a Item<'mir, 'tcx>) -> Self { - let analysis = FlowSensitiveAnalysis::new(q, item); - let results = dataflow::Engine::new_generic(item.tcx, &item.body, item.def_id, analysis) - .iterate_to_fixpoint(); - let cursor = dataflow::ResultsCursor::new(*item.body, results); + let cursor = FlowSensitiveAnalysis::new(q, item) + .into_engine(item.tcx, &item.body, item.def_id) + .iterate_to_fixpoint() + .into_results_cursor(*item.body); let mut in_any_value_of_ty = BitSet::new_empty(item.body.local_decls.len()); for (local, decl) in item.body.local_decls.iter_enumerated() {