]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #52433 - kennytm:rollup, r=kennytm
authorbors <bors@rust-lang.org>
Tue, 17 Jul 2018 13:31:35 +0000 (13:31 +0000)
committerbors <bors@rust-lang.org>
Tue, 17 Jul 2018 13:31:35 +0000 (13:31 +0000)
Rollup of 9 pull requests

Successful merges:

 - #52286 (Deny bare trait objects in src/librustc_errors)
 - #52306 (Reduce the number of clone()s needed in obligation_forest)
 - #52338 (update miri)
 - #52385 (Pass edition flags to compiler from rustdoc as expected)
 - #52392 (AsRef doc wording tweaks)
 - #52430 (update nomicon)
 - #52434 (Enable incremental independent of stage)
 - #52435 (Calculate the exact capacity for 2 HashMaps)
 - #52446 (Block beta if clippy breaks.)

r? @ghost

15 files changed:
src/librustc_data_structures/bitslice.rs
src/librustc_data_structures/bitvec.rs
src/librustc_data_structures/indexed_vec.rs
src/librustc_data_structures/lib.rs
src/librustc_mir/borrow_check/nll/constraint_generation.rs
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/values.rs
src/librustc_mir/borrow_check/nll/type_check/liveness.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/dataflow/impls/borrowed_locals.rs
src/librustc_mir/dataflow/impls/borrows.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/impls/storage_liveness.rs
src/librustc_mir/dataflow/mod.rs

index 2678861be0634e3588510406bc2f403ac40a5c6e..79435aa398779ae46c59e2ccb0e81b78f8897644 100644 (file)
@@ -28,9 +28,9 @@ impl BitSlice for [Word] {
     fn clear_bit(&mut self, idx: usize) -> bool {
         let words = self;
         debug!("clear_bit: words={} idx={}",
-               bits_to_string(words, words.len() * mem::size_of::<Word>()), bit_str(idx));
+               bits_to_string(words, words.len() * mem::size_of::<Word>() * 8), idx);
         let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx);
-        debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
+        debug!("word={} bit_in_word={} bit_mask=0x{:x}", word, bit_in_word, bit_mask);
         let oldv = words[word];
         let newv = oldv & !bit_mask;
         words[word] = newv;
@@ -42,7 +42,7 @@ fn clear_bit(&mut self, idx: usize) -> bool {
     fn set_bit(&mut self, idx: usize) -> bool {
         let words = self;
         debug!("set_bit: words={} idx={}",
-               bits_to_string(words, words.len() * mem::size_of::<Word>()), bit_str(idx));
+               bits_to_string(words, words.len() * mem::size_of::<Word>() * 8), idx);
         let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx);
         debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
         let oldv = words[word];
@@ -78,13 +78,6 @@ fn bit_lookup(bit: usize) -> BitLookup {
     BitLookup { word: word, bit_in_word: bit_in_word, bit_mask: bit_mask }
 }
 
-
-fn bit_str(bit: Word) -> String {
-    let byte = bit >> 3;
-    let lobits = 1 << (bit & 0b111);
-    format!("[{}:{}-{:02x}]", bit, byte, lobits)
-}
-
 pub fn bits_to_string(words: &[Word], bits: usize) -> String {
     let mut result = String::new();
     let mut sep = '[';
@@ -95,7 +88,7 @@ pub fn bits_to_string(words: &[Word], bits: usize) -> String {
     let mut i = 0;
     for &word in words.iter() {
         let mut v = word;
-        loop { // for each byte in `v`:
+        for _ in 0..mem::size_of::<Word>() { // for each byte in `v`:
             let remain = bits - i;
             // If less than a byte remains, then mask just that many bits.
             let mask = if remain <= 8 { (1 << remain) - 1 } else { 0xFF };
@@ -110,14 +103,15 @@ pub fn bits_to_string(words: &[Word], bits: usize) -> String {
             i += 8;
             sep = '-';
         }
+        sep = '|';
     }
     result.push(']');
     return result
 }
 
 #[inline]
-pub fn bitwise<Op:BitwiseOperator>(out_vec: &mut [usize],
-                                   in_vec: &[usize],
+pub fn bitwise<Op:BitwiseOperator>(out_vec: &mut [Word],
+                                   in_vec: &[Word],
                                    op: &Op) -> bool {
     assert_eq!(out_vec.len(), in_vec.len());
     let mut changed = false;
@@ -132,21 +126,21 @@ pub fn bitwise<Op:BitwiseOperator>(out_vec: &mut [usize],
 
 pub trait BitwiseOperator {
     /// Applies some bit-operation pointwise to each of the bits in the two inputs.
-    fn join(&self, pred1: usize, pred2: usize) -> usize;
+    fn join(&self, pred1: Word, pred2: Word) -> Word;
 }
 
 pub struct Intersect;
 impl BitwiseOperator for Intersect {
     #[inline]
-    fn join(&self, a: usize, b: usize) -> usize { a & b }
+    fn join(&self, a: Word, b: Word) -> Word { a & b }
 }
 pub struct Union;
 impl BitwiseOperator for Union {
     #[inline]
-    fn join(&self, a: usize, b: usize) -> usize { a | b }
+    fn join(&self, a: Word, b: Word) -> Word { a | b }
 }
 pub struct Subtract;
 impl BitwiseOperator for Subtract {
     #[inline]
-    fn join(&self, a: usize, b: usize) -> usize { a & !b }
+    fn join(&self, a: Word, b: Word) -> Word { a & !b }
 }
index a22dd1fececea5024fe76d917ad85c20d249f425..617153d5765b9cbb57762805e1229299583adb1a 100644 (file)
@@ -281,10 +281,10 @@ pub struct SparseBitMatrix<R, C>
 }
 
 impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
-    /// Create a new `rows x columns` matrix, initially empty.
-    pub fn new(rows: R, _columns: C) -> SparseBitMatrix<R, C> {
-        SparseBitMatrix {
-            vector: IndexVec::from_elem_n(SparseBitSet::new(), rows.index()),
+    /// Create a new empty sparse bit matrix with no rows or columns.
+    pub fn new() -> Self {
+        Self {
+            vector: IndexVec::new(),
         }
     }
 
@@ -293,6 +293,14 @@ pub fn new(rows: R, _columns: C) -> SparseBitMatrix<R, C> {
     ///
     /// Returns true if this changed the matrix, and false otherwise.
     pub fn add(&mut self, row: R, column: C) -> bool {
+        debug!(
+            "add(row={:?}, column={:?}, current_len={})",
+            row,
+            column,
+            self.vector.len()
+        );
+        self.vector
+            .ensure_contains_elem(row, || SparseBitSet::new());
         self.vector[row].insert(column)
     }
 
@@ -301,7 +309,7 @@ pub fn add(&mut self, row: R, column: C) -> bool {
     /// if the matrix represents (transitive) reachability, can
     /// `row` reach `column`?
     pub fn contains(&self, row: R, column: C) -> bool {
-        self.vector[row].contains(column)
+        self.vector.get(row).map_or(false, |r| r.contains(column))
     }
 
     /// Add the bits from row `read` to the bits from row `write`,
@@ -315,16 +323,27 @@ pub fn merge(&mut self, read: R, write: R) -> bool {
         let mut changed = false;
 
         if read != write {
-            let (bit_set_read, bit_set_write) = self.vector.pick2_mut(read, write);
+            if self.vector.get(read).is_some() {
+                self.vector
+                    .ensure_contains_elem(write, || SparseBitSet::new());
+                let (bit_set_read, bit_set_write) = self.vector.pick2_mut(read, write);
 
-            for read_chunk in bit_set_read.chunks() {
-                changed = changed | bit_set_write.insert_chunk(read_chunk).any();
+                for read_chunk in bit_set_read.chunks() {
+                    changed = changed | bit_set_write.insert_chunk(read_chunk).any();
+                }
             }
         }
 
         changed
     }
 
+    /// Merge a row, `from`, into the `into` row.
+    pub fn merge_into(&mut self, into: R, from: &SparseBitSet<C>) -> bool {
+        self.vector
+            .ensure_contains_elem(into, || SparseBitSet::new());
+        self.vector[into].insert_from(from)
+    }
+
     /// True if `sub` is a subset of `sup`
     pub fn is_subset(&self, sub: R, sup: R) -> bool {
         sub == sup || {
@@ -336,10 +355,20 @@ pub fn is_subset(&self, sub: R, sup: R) -> bool {
         }
     }
 
+    /// Number of elements in the matrix.
+    pub fn len(&self) -> usize {
+        self.vector.len()
+    }
+
     /// Iterates through all the columns set to true in a given row of
     /// the matrix.
     pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
-        self.vector[row].iter()
+        self.vector.get(row).into_iter().flat_map(|r| r.iter())
+    }
+
+    /// Iterates through each row and the accompanying bit set.
+    pub fn iter_enumerated<'a>(&'a self) -> impl Iterator<Item = (R, &'a SparseBitSet<C>)> + 'a {
+        self.vector.iter_enumerated()
     }
 }
 
@@ -445,6 +474,15 @@ pub fn insert_chunk(&mut self, chunk: SparseChunk<I>) -> SparseChunk<I> {
         }
     }
 
+    /// Insert into bit set from another bit set.
+    pub fn insert_from(&mut self, from: &SparseBitSet<I>) -> bool {
+        let mut changed = false;
+        for read_chunk in from.chunks() {
+            changed = changed | self.insert_chunk(read_chunk).any();
+        }
+        changed
+    }
+
     pub fn remove_chunk(&mut self, chunk: SparseChunk<I>) -> SparseChunk<I> {
         if chunk.bits == 0 {
             return chunk;
index 26de2191090e3a8d70dc9dd2b789fa56aadc3b0e..e7a75c149ccf03bdfc0ee56311a3603fe3f0ad3d 100644 (file)
@@ -518,10 +518,28 @@ pub fn convert_index_type<Ix: Idx>(self) -> IndexVec<Ix, T> {
 }
 
 impl<I: Idx, T: Clone> IndexVec<I, T> {
+    /// Grows the index vector so that it contains an entry for
+    /// `elem`; if that is already true, then has no
+    /// effect. Otherwise, inserts new values as needed by invoking
+    /// `fill_value`.
+    #[inline]
+    pub fn ensure_contains_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
+        let min_new_len = elem.index() + 1;
+        if self.len() < min_new_len {
+            self.raw.resize_with(min_new_len, fill_value);
+        }
+    }
+
     #[inline]
     pub fn resize(&mut self, new_len: usize, value: T) {
         self.raw.resize(new_len, value)
     }
+
+    #[inline]
+    pub fn resize_to_elem(&mut self, elem: I, fill_value: impl FnMut() -> T) {
+        let min_new_len = elem.index() + 1;
+        self.raw.resize_with(min_new_len, fill_value);
+    }
 }
 
 impl<I: Idx, T: Ord> IndexVec<I, T> {
index 508dc567fa01af71c632b569c5efe02c7a9b2524..b386f887d77f18a100e48b54a1b20528db56ed1d 100644 (file)
@@ -30,6 +30,7 @@
 #![feature(optin_builtin_traits)]
 #![feature(macro_vis_matcher)]
 #![feature(allow_internal_unstable)]
+#![feature(vec_resize_with)]
 
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(test, feature(test))]
index 68484888477c843400c60a734ce48fe1bd972ed4..f274f8e91894ea3a70ce4498addf130a165b5f98 100644 (file)
@@ -21,7 +21,6 @@
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts};
-use std::iter;
 
 pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
     infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
@@ -30,7 +29,6 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
     location_table: &LocationTable,
     mir: &Mir<'tcx>,
     borrow_set: &BorrowSet<'tcx>,
-    liveness_set_from_typeck: &[(ty::Region<'tcx>, Location)],
 ) {
     let mut cg = ConstraintGeneration {
         borrow_set,
@@ -40,8 +38,6 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
         all_facts,
     };
 
-    cg.add_region_liveness_constraints_from_type_check(liveness_set_from_typeck);
-
     for (bb, data) in mir.basic_blocks().iter_enumerated() {
         cg.visit_basic_block_data(bb, data);
     }
@@ -189,42 +185,6 @@ fn visit_user_assert_ty(
 }
 
 impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
-    /// The MIR type checker generates region liveness constraints
-    /// that we also have to respect.
-    fn add_region_liveness_constraints_from_type_check(
-        &mut self,
-        liveness_set: &[(ty::Region<'tcx>, Location)],
-    ) {
-        debug!(
-            "add_region_liveness_constraints_from_type_check(liveness_set={} items)",
-            liveness_set.len(),
-        );
-
-        let ConstraintGeneration {
-            regioncx,
-            location_table,
-            all_facts,
-            ..
-        } = self;
-
-        for (region, location) in liveness_set {
-            debug!("generate: {:#?} is live at {:#?}", region, location);
-            let region_vid = regioncx.to_region_vid(region);
-            regioncx.add_live_element(region_vid, *location);
-        }
-
-        if let Some(all_facts) = all_facts {
-            all_facts
-                .region_live_at
-                .extend(liveness_set.into_iter().flat_map(|(region, location)| {
-                    let r = regioncx.to_region_vid(region);
-                    let p1 = location_table.start_index(*location);
-                    let p2 = location_table.mid_index(*location);
-                    iter::once((r, p1)).chain(iter::once((r, p2)))
-                }));
-        }
-    }
-
     /// Some variable with type `live_ty` is "regular live" at
     /// `location` -- i.e., it may be used later. This means that all
     /// regions appearing in the type `live_ty` must be live at
index acd9223e42545c40453e49f78377eb415ecd4df4..5fcf46f6903797f33e2a1c3281c8ecc3eef9e4e9 100644 (file)
@@ -12,6 +12,7 @@
 use borrow_check::location::{LocationIndex, LocationTable};
 use borrow_check::nll::facts::AllFactsExt;
 use borrow_check::nll::type_check::MirTypeckRegionConstraints;
+use borrow_check::nll::region_infer::values::RegionValueElements;
 use dataflow::indexes::BorrowIndex;
 use dataflow::move_paths::MoveData;
 use dataflow::FlowAtLocation;
@@ -99,6 +100,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         None
     };
 
+    let elements = &Rc::new(RegionValueElements::new(mir, universal_regions.len()));
+
     // Run the MIR type-checker.
     let liveness = &LivenessResults::compute(mir);
     let constraint_sets = type_check::type_check(
@@ -113,6 +116,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         &mut all_facts,
         flow_inits,
         move_data,
+        elements,
     );
 
     if let Some(all_facts) = &mut all_facts {
@@ -126,7 +130,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     // base constraints generated by the type-check.
     let var_origins = infcx.take_region_var_origins();
     let MirTypeckRegionConstraints {
-        liveness_set,
+        liveness_constraints,
         outlives_constraints,
         type_tests,
     } = constraint_sets;
@@ -136,6 +140,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         mir,
         outlives_constraints,
         type_tests,
+        liveness_constraints,
+        elements,
     );
 
     // Generate various additional constraints.
@@ -146,7 +152,6 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         location_table,
         &mir,
         borrow_set,
-        &liveness_set,
     );
     invalidation::generate_invalidates(
         infcx,
index 369f6bd36f84603538ee34db60c3f099c5346385..5159fdc9fbabfbb1147eafa7dcf4a6a868c80a13 100644 (file)
@@ -37,7 +37,7 @@
 mod dump_mir;
 mod error_reporting;
 mod graphviz;
-mod values;
+pub mod values;
 use self::values::{RegionValueElements, RegionValues};
 
 use super::ToRegionVid;
@@ -66,8 +66,8 @@ pub struct RegionInferenceContext<'tcx> {
     /// the SCC (see `constraint_sccs`) and for error reporting.
     constraint_graph: Rc<ConstraintGraph>,
 
-    /// The SCC computed from `constraints` and
-    /// `constraint_graph`. Used to compute the values of each region.
+    /// The SCC computed from `constraints` and the constraint graph. Used to compute the values
+    /// of each region.
     constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
 
     /// The final inferred values of the region variables; we compute
@@ -207,15 +207,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(crate) fn new(
         var_infos: VarInfos,
         universal_regions: UniversalRegions<'tcx>,
-        mir: &Mir<'tcx>,
+        _mir: &Mir<'tcx>,
         outlives_constraints: ConstraintSet,
         type_tests: Vec<TypeTest<'tcx>>,
+        liveness_constraints: RegionValues<RegionVid>,
+        elements: &Rc<RegionValueElements>,
     ) -> Self {
         let universal_regions = Rc::new(universal_regions);
-        let num_region_variables = var_infos.len();
-        let num_universal_regions = universal_regions.len();
-
-        let elements = &Rc::new(RegionValueElements::new(mir, num_universal_regions));
 
         // Create a RegionDefinition for each inference variable.
         let definitions: IndexVec<_, _> = var_infos
@@ -227,15 +225,20 @@ pub(crate) fn new(
         let constraint_graph = Rc::new(constraints.graph(definitions.len()));
         let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph));
 
-        let scc_values = RegionValues::new(elements, constraint_sccs.num_sccs());
+        let mut scc_values = RegionValues::new(elements);
+
+        for (region, location_set) in liveness_constraints.iter_enumerated() {
+            let scc = constraint_sccs.scc(region);
+            scc_values.merge_into(scc, location_set);
+        }
 
         let mut result = Self {
             definitions,
             elements: elements.clone(),
-            liveness_constraints: RegionValues::new(elements, num_region_variables),
+            liveness_constraints,
             constraints,
-            constraint_sccs,
             constraint_graph,
+            constraint_sccs,
             scc_values,
             type_tests,
             universal_regions,
@@ -414,7 +417,7 @@ fn propagate_constraints(&mut self, _mir: &Mir<'tcx>) {
             constraints
         });
 
-        // To propagate constriants, we walk the DAG induced by the
+        // To propagate constraints, we walk the DAG induced by the
         // SCC. For each SCC, we visit its successors and compute
         // their values, then we union all those values to get our
         // own.
index c5bfb1fc6a588addd9254223423593d56f1e6c78..f041483a8ff2f985226f7d2514072ed2c099428b 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::mir::{BasicBlock, Location, Mir};
 use rustc::ty::RegionVid;
-use rustc_data_structures::bitvec::SparseBitMatrix;
+use rustc_data_structures::bitvec::{SparseBitMatrix, SparseBitSet};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::fmt::Debug;
@@ -55,11 +55,6 @@ impl RegionValueElements {
         }
     }
 
-    /// Total number of element indices that exist.
-    crate fn num_elements(&self) -> usize {
-        self.num_points + self.num_universal_regions
-    }
-
     /// Converts an element of a region value into a `RegionElementIndex`.
     crate fn index<T: ToElementIndex>(&self, elem: T) -> RegionElementIndex {
         elem.to_element_index(self)
@@ -188,18 +183,10 @@ impl<N: Idx> RegionValues<N> {
     /// Creates a new set of "region values" that tracks causal information.
     /// Each of the regions in num_region_variables will be initialized with an
     /// empty set of points and no causal information.
-    crate fn new(elements: &Rc<RegionValueElements>, num_region_variables: usize) -> Self {
-        assert!(
-            elements.num_universal_regions <= num_region_variables,
-            "universal regions are a subset of the region variables"
-        );
-
+    crate fn new(elements: &Rc<RegionValueElements>) -> Self {
         Self {
             elements: elements.clone(),
-            matrix: SparseBitMatrix::new(
-                N::new(num_region_variables),
-                RegionElementIndex::new(elements.num_elements()),
-            ),
+            matrix: SparseBitMatrix::new(),
         }
     }
 
@@ -227,6 +214,18 @@ impl<N: Idx> RegionValues<N> {
         self.matrix.contains(r, i)
     }
 
+    /// Iterates through each row and the accompanying bit set.
+    pub fn iter_enumerated<'a>(
+        &'a self
+    ) -> impl Iterator<Item = (N, &'a SparseBitSet<RegionElementIndex>)> + 'a {
+        self.matrix.iter_enumerated()
+    }
+
+    /// Merge a row, `from`, originating in another `RegionValues` into the `into` row.
+    pub fn merge_into(&mut self, into: N, from: &SparseBitSet<RegionElementIndex>) -> bool {
+        self.matrix.merge_into(into, from)
+    }
+
     /// True if `sup_region` contains all the CFG points that
     /// `sub_region` contains. Ignores universal regions.
     crate fn contains_points(&self, sup_region: N, sub_region: N) -> bool {
index 91025e3f4afc016e13e7d2048f1fd19baaccc06a..cd468eabd5f8beb9dd933915c94410be157eebe9 100644 (file)
@@ -168,7 +168,18 @@ fn push_type_live_constraint<T>(
         );
 
         cx.tcx().for_each_free_region(&value, |live_region| {
-            cx.constraints.liveness_set.push((live_region, location));
+            if let Some(ref mut borrowck_context) = cx.borrowck_context {
+                let region_vid = borrowck_context.universal_regions.to_region_vid(live_region);
+                borrowck_context.constraints.liveness_constraints.add_element(region_vid, location);
+
+                if let Some(all_facts) = borrowck_context.all_facts {
+                    let start_index = borrowck_context.location_table.start_index(location);
+                    all_facts.region_live_at.push((region_vid, start_index));
+
+                    let mid_index = borrowck_context.location_table.mid_index(location);
+                    all_facts.region_live_at.push((region_vid, mid_index));
+                }
+            }
         });
     }
 
index 25f2be231772d58cfaaea9e108a6ca6cda522802..e188c9d7559c92dd8fded791cd8ffd64a2a4c6d3 100644 (file)
@@ -16,6 +16,7 @@
 use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
 use borrow_check::nll::facts::AllFacts;
 use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
+use borrow_check::nll::region_infer::values::{RegionValues, RegionValueElements};
 use borrow_check::nll::universal_regions::UniversalRegions;
 use borrow_check::nll::ToRegionVid;
 use dataflow::move_paths::MoveData;
@@ -33,8 +34,9 @@
 use rustc::traits::query::type_op;
 use rustc::traits::query::{Fallible, NoSolution};
 use rustc::ty::fold::TypeFoldable;
-use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
+use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants, RegionVid};
 use std::fmt;
+use std::rc::Rc;
 use syntax_pos::{Span, DUMMY_SP};
 use transform::{MirPass, MirSource};
 use util::liveness::LivenessResults;
@@ -111,39 +113,55 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     all_facts: &mut Option<AllFacts>,
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'_, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,
+    elements: &Rc<RegionValueElements>,
 ) -> MirTypeckRegionConstraints<'tcx> {
     let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
-    type_check_internal(
-        infcx,
-        mir_def_id,
-        param_env,
-        mir,
-        &universal_regions.region_bound_pairs,
-        Some(implicit_region_bound),
-        Some(BorrowCheckContext {
+    let mut constraints = MirTypeckRegionConstraints {
+        liveness_constraints: RegionValues::new(elements),
+        outlives_constraints: ConstraintSet::default(),
+        type_tests: Vec::default(),
+    };
+
+    {
+        let mut borrowck_context = BorrowCheckContext {
             universal_regions,
             location_table,
             borrow_set,
             all_facts,
-        }),
-        &mut |cx| {
-            liveness::generate(cx, mir, liveness, flow_inits, move_data);
+            constraints: &mut constraints,
+        };
+
+        type_check_internal(
+            infcx,
+            mir_def_id,
+            param_env,
+            mir,
+            &universal_regions.region_bound_pairs,
+            Some(implicit_region_bound),
+            Some(&mut borrowck_context),
+            |cx| {
+                liveness::generate(cx, mir, liveness, flow_inits, move_data);
 
-            cx.equate_inputs_and_outputs(mir, mir_def_id, universal_regions);
-        },
-    )
+                cx.equate_inputs_and_outputs(mir, mir_def_id, universal_regions);
+            },
+        );
+    }
+
+    constraints
 }
 
-fn type_check_internal<'gcx, 'tcx>(
-    infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+fn type_check_internal<'a, 'gcx, 'tcx, F>(
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     mir_def_id: DefId,
     param_env: ty::ParamEnv<'gcx>,
-    mir: &Mir<'tcx>,
-    region_bound_pairs: &[(ty::Region<'tcx>, GenericKind<'tcx>)],
+    mir: &'a Mir<'tcx>,
+    region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
     implicit_region_bound: Option<ty::Region<'tcx>>,
-    borrowck_context: Option<BorrowCheckContext<'_, 'tcx>>,
-    extra: &mut dyn FnMut(&mut TypeChecker<'_, 'gcx, 'tcx>),
-) -> MirTypeckRegionConstraints<'tcx> {
+    borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
+    mut extra: F,
+)
+    where F: FnMut(&mut TypeChecker<'a, 'gcx, 'tcx>)
+{
     let mut checker = TypeChecker::new(
         infcx,
         mir,
@@ -165,8 +183,6 @@ fn type_check_internal<'gcx, 'tcx>(
     }
 
     extra(&mut checker);
-
-    checker.constraints
 }
 
 fn mirbug(tcx: TyCtxt, span: Span, msg: &str) {
@@ -603,8 +619,7 @@ struct TypeChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
     implicit_region_bound: Option<ty::Region<'tcx>>,
     reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
-    constraints: MirTypeckRegionConstraints<'tcx>,
-    borrowck_context: Option<BorrowCheckContext<'a, 'tcx>>,
+    borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
 }
 
 struct BorrowCheckContext<'a, 'tcx: 'a> {
@@ -612,11 +627,11 @@ struct BorrowCheckContext<'a, 'tcx: 'a> {
     location_table: &'a LocationTable,
     all_facts: &'a mut Option<AllFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
+    constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
 }
 
 /// A collection of region constraints that must be satisfied for the
 /// program to be considered well-typed.
-#[derive(Default)]
 crate struct MirTypeckRegionConstraints<'tcx> {
     /// In general, the type-checker is not responsible for enforcing
     /// liveness constraints; this job falls to the region inferencer,
@@ -625,7 +640,7 @@ struct BorrowCheckContext<'a, 'tcx: 'a> {
     /// not otherwise appear in the MIR -- in particular, the
     /// late-bound regions that it instantiates at call-sites -- and
     /// hence it must report on their liveness constraints.
-    crate liveness_set: Vec<(ty::Region<'tcx>, Location)>,
+    crate liveness_constraints: RegionValues<RegionVid>,
 
     crate outlives_constraints: ConstraintSet,
 
@@ -717,7 +732,7 @@ fn new(
         param_env: ty::ParamEnv<'gcx>,
         region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)],
         implicit_region_bound: Option<ty::Region<'tcx>>,
-        borrowck_context: Option<BorrowCheckContext<'a, 'tcx>>,
+        borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>,
     ) -> Self {
         TypeChecker {
             infcx,
@@ -729,7 +744,6 @@ fn new(
             implicit_region_bound,
             borrowck_context,
             reported_errors: FxHashSet(),
-            constraints: MirTypeckRegionConstraints::default(),
         }
     }
 
@@ -767,7 +781,7 @@ fn push_region_constraints(
             locations, data
         );
 
-        if let Some(borrowck_context) = &mut self.borrowck_context {
+        if let Some(ref mut borrowck_context) = self.borrowck_context {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx.tcx,
                 borrowck_context.universal_regions,
@@ -776,8 +790,8 @@ fn push_region_constraints(
                 self.implicit_region_bound,
                 self.param_env,
                 locations,
-                &mut self.constraints.outlives_constraints,
-                &mut self.constraints.type_tests,
+                &mut borrowck_context.constraints.outlives_constraints,
+                &mut borrowck_context.constraints.type_tests,
                 &mut borrowck_context.all_facts,
             ).convert_all(&data);
         }
@@ -993,9 +1007,13 @@ fn check_terminator(
                 // output) types in the signature must be live, since
                 // all the inputs that fed into it were live.
                 for &late_bound_region in map.values() {
-                    self.constraints
-                        .liveness_set
-                        .push((late_bound_region, term_location));
+                    if let Some(ref mut borrowck_context) = self.borrowck_context {
+                        let region_vid = borrowck_context.universal_regions.to_region_vid(
+                            late_bound_region);
+                        borrowck_context.constraints
+                            .liveness_constraints
+                            .add_element(region_vid, term_location);
+                    }
                 }
 
                 self.check_call_inputs(mir, term, &sig, args, term_location);
@@ -1487,9 +1505,10 @@ fn add_reborrow_constraint(
             borrow_set,
             location_table,
             all_facts,
+            constraints,
             ..
-        } = match &mut self.borrowck_context {
-            Some(borrowck_context) => borrowck_context,
+        } = match self.borrowck_context {
+            Some(ref mut borrowck_context) => borrowck_context,
             None => return,
         };
 
@@ -1531,7 +1550,7 @@ fn add_reborrow_constraint(
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.sty {
                         ty::TyRef(ref_region, _, mutbl) => {
-                            self.constraints
+                            constraints
                                 .outlives_constraints
                                 .push(OutlivesConstraint {
                                     sup: ref_region.to_region_vid(),
@@ -1792,8 +1811,7 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &
 
         let param_env = tcx.param_env(def_id);
         tcx.infer_ctxt().enter(|infcx| {
-            let _ =
-                type_check_internal(&infcx, def_id, param_env, mir, &[], None, None, &mut |_| ());
+            type_check_internal(&infcx, def_id, param_env, mir, &[], None, None, |_| ());
 
             // For verification purposes, we just ignore the resulting
             // region constraint sets. Not our problem. =)
index 244e8b5ccd7e4b4d45e0259ccd730f9951d66768..c7513ac88163aa11bd9a2b88902552f61cb4747a 100644 (file)
@@ -74,7 +74,7 @@ fn propagate_call_return(&self,
 
 impl<'a, 'tcx> BitwiseOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
     #[inline]
-    fn join(&self, pred1: usize, pred2: usize) -> usize {
+    fn join(&self, pred1: Word, pred2: Word) -> Word {
         pred1 | pred2 // "maybe" means we union effects of both preds
     }
 }
index 9736ab797b2c14967f68ff9cbd93fad62239b6d4..5bf54286875a1f4ab1f7671d1b3ec5059621c8a9 100644 (file)
@@ -20,7 +20,7 @@
 use rustc::ty::{RegionKind, RegionVid};
 use rustc::ty::RegionKind::ReScope;
 
-use rustc_data_structures::bitslice::BitwiseOperator;
+use rustc_data_structures::bitslice::{BitwiseOperator, Word};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_set::IdxSet;
 use rustc_data_structures::indexed_vec::IndexVec;
@@ -370,7 +370,7 @@ fn propagate_call_return(&self,
 
 impl<'a, 'gcx, 'tcx> BitwiseOperator for Borrows<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: usize, pred2: usize) -> usize {
+    fn join(&self, pred1: Word, pred2: Word) -> Word {
         pred1 | pred2 // union effects of preds when computing reservations
     }
 }
index f64fd64b283ea5ea63ad992123d702695f28bffa..ee3bba840c67bfbfe19d79074103aee29501524e 100644 (file)
@@ -14,7 +14,7 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::{self, Mir, Location};
-use rustc_data_structures::bitslice::{BitwiseOperator};
+use rustc_data_structures::bitslice::{BitwiseOperator, Word};
 use rustc_data_structures::indexed_set::{IdxSet};
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -663,35 +663,35 @@ fn propagate_call_return(&self,
 
 impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: usize, pred2: usize) -> usize {
+    fn join(&self, pred1: Word, pred2: Word) -> Word {
         pred1 | pred2 // "maybe" means we union effects of both preds
     }
 }
 
 impl<'a, 'gcx, 'tcx> BitwiseOperator for MaybeUninitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: usize, pred2: usize) -> usize {
+    fn join(&self, pred1: Word, pred2: Word) -> Word {
         pred1 | pred2 // "maybe" means we union effects of both preds
     }
 }
 
 impl<'a, 'gcx, 'tcx> BitwiseOperator for DefinitelyInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: usize, pred2: usize) -> usize {
+    fn join(&self, pred1: Word, pred2: Word) -> Word {
         pred1 & pred2 // "definitely" means we intersect effects of both preds
     }
 }
 
 impl<'a, 'gcx, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: usize, pred2: usize) -> usize {
+    fn join(&self, pred1: Word, pred2: Word) -> Word {
         pred1 | pred2 // moves from both preds are in scope
     }
 }
 
 impl<'a, 'gcx, 'tcx> BitwiseOperator for EverInitializedPlaces<'a, 'gcx, 'tcx> {
     #[inline]
-    fn join(&self, pred1: usize, pred2: usize) -> usize {
+    fn join(&self, pred1: Word, pred2: Word) -> Word {
         pred1 | pred2 // inits from both preds are in scope
     }
 }
index dea61542ac4e2e7616deddfc2313bb1e0c0ca748..29548051a4d927e73b36c74af845fa84671a3a92 100644 (file)
@@ -69,7 +69,7 @@ fn propagate_call_return(&self,
 
 impl<'a, 'tcx> BitwiseOperator for MaybeStorageLive<'a, 'tcx> {
     #[inline]
-    fn join(&self, pred1: usize, pred2: usize) -> usize {
+    fn join(&self, pred1: Word, pred2: Word) -> Word {
         pred1 | pred2 // "maybe" means we union effects of both preds
     }
 }
index e3b67b0a003efd2b202deafa16a4953f5466e885..f58609aa9a5163403d6d426cd66d91732a5e1809 100644 (file)
@@ -12,7 +12,7 @@
 
 use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
 use rustc_data_structures::indexed_vec::Idx;
-use rustc_data_structures::bitslice::{bitwise, BitwiseOperator};
+use rustc_data_structures::bitslice::{bitwise, BitwiseOperator, Word};
 use rustc_data_structures::work_queue::WorkQueue;
 
 use rustc::ty::{self, TyCtxt};
@@ -467,7 +467,7 @@ pub struct AllSets<E: Idx> {
     bits_per_block: usize,
 
     /// Number of words associated with each block entry
-    /// equal to bits_per_block / usize::BITS, rounded up.
+    /// equal to bits_per_block / (mem::size_of::<Word> * 8), rounded up.
     words_per_block: usize,
 
     /// For each block, bits generated by executing the statements in
@@ -734,9 +734,11 @@ pub fn new(mir: &'a Mir<'tcx>,
                dead_unwinds: &'a IdxSet<mir::BasicBlock>,
                denotation: D) -> Self where D: InitialFlow {
         let bits_per_block = denotation.bits_per_block();
-        let usize_bits = mem::size_of::<usize>() * 8;
-        let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;
-        let num_overall = Self::num_bits_overall(mir, bits_per_block);
+        let bits_per_word = mem::size_of::<Word>() * 8;
+        let words_per_block = (bits_per_block + bits_per_word - 1) / bits_per_word;
+        let bits_per_block_rounded_up = words_per_block * bits_per_word; // a multiple of word size
+        let num_blocks = mir.basic_blocks().len();
+        let num_overall = num_blocks * bits_per_block_rounded_up;
 
         let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall));
         let on_entry = Bits::new(if D::bottom_value() {
@@ -774,18 +776,6 @@ pub fn new_from_sets(mir: &'a Mir<'tcx>,
             }
         }
     }
-
-    fn num_bits_overall(mir: &Mir, bits_per_block: usize) -> usize {
-        let usize_bits = mem::size_of::<usize>() * 8;
-        let words_per_block = (bits_per_block + usize_bits - 1) / usize_bits;
-
-        // (now rounded up to multiple of word size)
-        let bits_per_block = words_per_block * usize_bits;
-
-        let num_blocks = mir.basic_blocks().len();
-        let num_overall = num_blocks * bits_per_block;
-        num_overall
-    }
 }
 
 impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation