diff --git a/polonius-engine/src/output/hybrid.rs b/polonius-engine/src/output/hybrid.rs new file mode 100644 index 00000000000..f1912a09a70 --- /dev/null +++ b/polonius-engine/src/output/hybrid.rs @@ -0,0 +1,29 @@ +// Copyright 2019 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A hybrid version combining the optimized Datafrog model with the +//! location-insensitive version. + +use crate::output::datafrog_opt; +use crate::output::location_insensitive; +use crate::output::Output; +use facts::{AllFacts, Atom}; + +pub(super) fn compute( + dump_enabled: bool, + all_facts: AllFacts, +) -> Output { + let lins_output = location_insensitive::compute(dump_enabled, &all_facts); + if lins_output.errors.is_empty() { + lins_output + } else { + datafrog_opt::compute(dump_enabled, all_facts) + } +} diff --git a/polonius-engine/src/output/location_insensitive.rs b/polonius-engine/src/output/location_insensitive.rs index 40f0bda9f03..d9e7bc4057c 100644 --- a/polonius-engine/src/output/location_insensitive.rs +++ b/polonius-engine/src/output/location_insensitive.rs @@ -18,7 +18,7 @@ use facts::{AllFacts, Atom}; pub(super) fn compute( dump_enabled: bool, - mut all_facts: AllFacts, + all_facts: &AllFacts, ) -> Output { let all_points: BTreeSet = all_facts .cfg_edge @@ -27,12 +27,11 @@ pub(super) fn compute( .chain(all_facts.cfg_edge.iter().map(|&(_, q)| q)) .collect(); - all_facts - .region_live_at - .reserve(all_facts.universal_region.len() * all_points.len()); + let mut region_live_at = all_facts.region_live_at.clone(); + region_live_at.reserve(all_facts.universal_region.len() * all_points.len()); for &r in &all_facts.universal_region { for &p in &all_points { - all_facts.region_live_at.push((r, p)); + region_live_at.push((r, p)); } } @@ -45,7 +44,7 @@ pub(super) fn compute( let mut iteration = Iteration::new(); // static inputs - let region_live_at: Relation<(Region, Point)> = all_facts.region_live_at.into(); + let region_live_at: Relation<(Region, Point)> = region_live_at.into(); let invalidates = Relation::from_iter(all_facts.invalidates.iter().map(|&(b, p)| (p, b))); // .. some variables, .. diff --git a/polonius-engine/src/output/mod.rs b/polonius-engine/src/output/mod.rs index 19d225a67c3..78d409f66c5 100644 --- a/polonius-engine/src/output/mod.rs +++ b/polonius-engine/src/output/mod.rs @@ -13,6 +13,7 @@ use std::borrow::Cow; use std::collections::{BTreeMap, BTreeSet}; mod datafrog_opt; +mod hybrid; mod location_insensitive; mod naive; use facts::{AllFacts, Atom}; @@ -24,14 +25,21 @@ pub enum Algorithm { LocationInsensitive, /// Compare Naive and DatafrogOpt. Compare, + Hybrid, } impl Algorithm { /// Optimized variants that ought to be equivalent to "naive" pub const OPTIMIZED: &'static [Algorithm] = &[Algorithm::DatafrogOpt]; - pub fn variants() -> [&'static str; 4] { - ["Naive", "DatafrogOpt", "LocationInsensitive", "Compare"] + pub fn variants() -> [&'static str; 5] { + [ + "Naive", + "DatafrogOpt", + "LocationInsensitive", + "Compare", + "Hybrid", + ] } } @@ -43,8 +51,9 @@ impl ::std::str::FromStr for Algorithm { "datafrogopt" => Ok(Algorithm::DatafrogOpt), "locationinsensitive" => Ok(Algorithm::LocationInsensitive), "compare" => Ok(Algorithm::Compare), + "hybrid" => Ok(Algorithm::Hybrid), _ => Err(String::from( - "valid values: Naive, DatafrogOpt, LocationInsensitive, Compare", + "valid values: Naive, DatafrogOpt, LocationInsensitive, Compare, Hybrid", )), } } @@ -117,7 +126,7 @@ where Algorithm::Naive => naive::compute(dump_enabled, all_facts.clone()), Algorithm::DatafrogOpt => datafrog_opt::compute(dump_enabled, all_facts.clone()), Algorithm::LocationInsensitive => { - location_insensitive::compute(dump_enabled, all_facts.clone()) + location_insensitive::compute(dump_enabled, &all_facts) } Algorithm::Compare => { let naive_output = naive::compute(dump_enabled, all_facts.clone()); @@ -133,6 +142,7 @@ where } opt_output } + Algorithm::Hybrid => hybrid::compute(dump_enabled, all_facts.clone()), } } diff --git a/src/test.rs b/src/test.rs index f9798eae730..6f0c658506b 100644 --- a/src/test.rs +++ b/src/test.rs @@ -48,6 +48,10 @@ fn test_facts(all_facts: &AllFacts, algorithms: &[Algorithm]) { assert_equal(&naive.borrow_live_at, &opt.borrow_live_at); assert_equal(&naive.errors, &opt.errors); } + + // The hybrid algorithm gets the same errors as the naive version + let opt = Output::compute(all_facts, Algorithm::Hybrid, true); + assert_equal(&naive.errors, &opt.errors); } fn test_fn(dir_name: &str, fn_name: &str, algorithm: Algorithm) -> Result<(), Error> {