From 8b94d1605be5a73a7e0362d26bdabfeca1250719 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 9 Jul 2018 21:26:20 +0100 Subject: [PATCH] Generate region values directly to reduce memory usage. Also modify `SparseBitMatrix` so that it does not require knowing the dimensions in advance, but instead grows on demand. --- src/librustc_data_structures/bitvec.rs | 56 ++++++++-- src/librustc_data_structures/indexed_vec.rs | 18 ++++ src/librustc_data_structures/lib.rs | 1 + .../borrow_check/nll/constraint_generation.rs | 40 ------- src/librustc_mir/borrow_check/nll/mod.rs | 9 +- .../borrow_check/nll/region_infer/mod.rs | 27 ++--- .../borrow_check/nll/region_infer/values.rs | 31 +++--- .../borrow_check/nll/type_check/liveness.rs | 13 ++- .../borrow_check/nll/type_check/mod.rs | 100 +++++++++++------- 9 files changed, 174 insertions(+), 121 deletions(-) diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index a22dd1fececea..617153d5765b9 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -281,10 +281,10 @@ where } impl SparseBitMatrix { - /// Create a new `rows x columns` matrix, initially empty. - pub fn new(rows: R, _columns: C) -> SparseBitMatrix { - 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 @@ impl SparseBitMatrix { /// /// 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 @@ impl SparseBitMatrix { /// 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 @@ impl SparseBitMatrix { 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) -> 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 @@ impl SparseBitMatrix { } } + /// 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 + '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)> + 'a { + self.vector.iter_enumerated() } } @@ -445,6 +474,15 @@ impl SparseBitSet { } } + /// Insert into bit set from another bit set. + pub fn insert_from(&mut self, from: &SparseBitSet) -> 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) -> SparseChunk { if chunk.bits == 0 { return chunk; diff --git a/src/librustc_data_structures/indexed_vec.rs b/src/librustc_data_structures/indexed_vec.rs index 26de2191090e3..e7a75c149ccf0 100644 --- a/src/librustc_data_structures/indexed_vec.rs +++ b/src/librustc_data_structures/indexed_vec.rs @@ -518,10 +518,28 @@ impl IndexVec { } impl IndexVec { + /// 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 IndexVec { diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 508dc567fa01a..b386f887d77f1 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -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))] diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 68484888477c8..f274f8e91894e 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -21,7 +21,6 @@ use rustc::mir::{Local, Statement, Terminator}; 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 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx } 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 diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index acd9223e42545..5fcf46f690379 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -12,6 +12,7 @@ use borrow_check::borrow_set::BorrowSet; 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, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 369f6bd36f846..5159fdc9fbabf 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -37,7 +37,7 @@ mod annotation; 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, - /// 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>, /// 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>, + liveness_constraints: RegionValues, + elements: &Rc, ) -> 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 @@ impl<'tcx> RegionInferenceContext<'tcx> { 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 @@ impl<'tcx> RegionInferenceContext<'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. diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index c5bfb1fc6a588..f041483a8ff2f 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -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(&self, elem: T) -> RegionElementIndex { elem.to_element_index(self) @@ -188,18 +183,10 @@ impl RegionValues { /// 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, 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) -> 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 RegionValues { self.matrix.contains(r, i) } + /// Iterates through each row and the accompanying bit set. + pub fn iter_enumerated<'a>( + &'a self + ) -> impl Iterator)> + '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) -> 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 { diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index 91025e3f4afc0..cd468eabd5f8b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -168,7 +168,18 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo ); 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)); + } + } }); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 25f2be231772d..e188c9d7559c9 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -16,6 +16,7 @@ use borrow_check::location::LocationTable; 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::mir::*; 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, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, + elements: &Rc, ) -> 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>, - borrowck_context: Option>, - 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>, reported_errors: FxHashSet<(Ty<'tcx>, Span)>, - constraints: MirTypeckRegionConstraints<'tcx>, - borrowck_context: Option>, + 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, 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 @@ crate struct MirTypeckRegionConstraints<'tcx> { /// 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, crate outlives_constraints: ConstraintSet, @@ -717,7 +732,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { param_env: ty::ParamEnv<'gcx>, region_bound_pairs: &'a [(ty::Region<'tcx>, GenericKind<'tcx>)], implicit_region_bound: Option>, - borrowck_context: Option>, + borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>, ) -> Self { TypeChecker { infcx, @@ -729,7 +744,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { implicit_region_bound, borrowck_context, reported_errors: FxHashSet(), - constraints: MirTypeckRegionConstraints::default(), } } @@ -767,7 +781,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // 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 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { 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 @@ impl MirPass for TypeckMir { 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. =)