diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-10-01 10:13:13 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2018-10-27 08:41:12 -0400 |
| commit | 784746f57e6e9d76f4ecc0415e8ab926a81ce37e (patch) | |
| tree | f60afcbd64473abc60bef1c4b4a8ffee9933801e | |
| parent | 018c515f077597ad45f85d962a49ab6fbc5421ac (diff) | |
| download | rust-784746f57e6e9d76f4ecc0415e8ab926a81ce37e.tar.gz rust-784746f57e6e9d76f4ecc0415e8ab926a81ce37e.zip | |
convert placeholder region vids in NLL mode as we see them
7 files changed, 88 insertions, 38 deletions
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 03cdb5f4cb8..0c4140caee8 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -134,6 +134,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( let var_origins = infcx.take_region_var_origins(); let MirTypeckRegionConstraints { placeholder_indices, + placeholder_index_to_region: _, mut liveness_constraints, outlives_constraints, closure_bounds_mapping, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index ccb44c670f7..64135195637 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -594,6 +594,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Finds some region R such that `fr1: R` and `R` is live at // `elem`. crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid { + debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem); // Find all paths let (_path, r) = self.find_constraint_paths_between_regions(fr1, |r| { 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 50fd4afcd7e..0e44c8b36a9 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -1226,6 +1226,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); let longer_fr_scc = self.constraint_sccs.scc(longer_fr); + debug!( + "check_bound_universal_region: longer_fr_scc={:?}", + longer_fr_scc, + ); // If we have some bound universal region `'a`, then the only // elements it can contain is itself -- we don't know anything @@ -1242,6 +1246,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { Some(v) => v, None => return, }; + debug!("check_bound_universal_region: error_element = {:?}", error_element); // Find the region that introduced this `error_element`. let error_region = match error_element { diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs index 994f20a011d..5904138ef60 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs @@ -8,21 +8,23 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint}; +use borrow_check::nll::constraints::OutlivesConstraint; use borrow_check::nll::region_infer::TypeTest; -use borrow_check::nll::type_check::Locations; +use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints}; use borrow_check::nll::universal_regions::UniversalRegions; +use borrow_check::nll::ToRegionVid; use rustc::infer::canonical::QueryRegionConstraint; use rustc::infer::outlives::env::RegionBoundPairs; use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc::infer::region_constraints::{GenericKind, VerifyBound}; -use rustc::infer::{self, SubregionOrigin}; +use rustc::infer::{self, InferCtxt, SubregionOrigin}; use rustc::mir::ConstraintCategory; use rustc::ty::subst::UnpackedKind; use rustc::ty::{self, TyCtxt}; use syntax_pos::DUMMY_SP; crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> { + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>, universal_regions: &'a UniversalRegions<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, @@ -30,32 +32,30 @@ crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> { param_env: ty::ParamEnv<'tcx>, locations: Locations, category: ConstraintCategory, - outlives_constraints: &'a mut ConstraintSet, - type_tests: &'a mut Vec<TypeTest<'tcx>>, + constraints: &'a mut MirTypeckRegionConstraints<'tcx>, } impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> { crate fn new( - tcx: TyCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, universal_regions: &'a UniversalRegions<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: Option<ty::Region<'tcx>>, param_env: ty::ParamEnv<'tcx>, locations: Locations, category: ConstraintCategory, - outlives_constraints: &'a mut ConstraintSet, - type_tests: &'a mut Vec<TypeTest<'tcx>>, + constraints: &'a mut MirTypeckRegionConstraints<'tcx>, ) -> Self { Self { - tcx, + infcx, + tcx: infcx.tcx, universal_regions, region_bound_pairs, implicit_region_bound, param_env, locations, category, - outlives_constraints, - type_tests, + constraints, } } @@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> { } fn verify_to_type_test( - &self, + &mut self, generic_kind: GenericKind<'tcx>, region: ty::Region<'tcx>, verify_bound: VerifyBound<'tcx>, @@ -128,22 +128,30 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> { } } - fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid { - self.universal_regions.to_region_vid(r) + fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid { + if let ty::RePlaceholder(placeholder) = r { + self.constraints + .placeholder_region(self.infcx, *placeholder) + .to_region_vid() + } else { + self.universal_regions.to_region_vid(r) + } } fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) { - self.outlives_constraints.push(OutlivesConstraint { - locations: self.locations, - category: self.category, - sub, - sup, - }); + self.constraints + .outlives_constraints + .push(OutlivesConstraint { + locations: self.locations, + category: self.category, + sub, + sup, + }); } fn add_type_test(&mut self, type_test: TypeTest<'tcx>) { debug!("add_type_test(type_test={:?})", type_test); - self.type_tests.push(type_test); + self.constraints.type_tests.push(type_test); } } @@ -156,8 +164,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx> a: ty::Region<'tcx>, b: ty::Region<'tcx>, ) { - let b = self.universal_regions.to_region_vid(b); - let a = self.universal_regions.to_region_vid(a); + let b = self.to_region_vid(b); + let a = self.to_region_vid(a); self.add_outlives(b, a); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs index f8c839e4d3f..3d0f3d9fc7d 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs @@ -271,15 +271,14 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> { for data in constraint_sets { constraint_conversion::ConstraintConversion::new( - self.infcx.tcx, + self.infcx, &self.universal_regions, &self.region_bound_pairs, self.implicit_region_bound, self.param_env, Locations::All(DUMMY_SP), ConstraintCategory::Internal, - &mut self.constraints.outlives_constraints, - &mut self.constraints.type_tests, + &mut self.constraints, ).convert_all(&data); } 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 bcf73c5c644..eae41c81ff2 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::values::LivenessValues; +use borrow_check::nll::region_infer::values::PlaceholderIndex; use borrow_check::nll::region_infer::values::PlaceholderIndices; use borrow_check::nll::region_infer::values::RegionValueElements; use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; @@ -28,11 +29,12 @@ use borrow_check::nll::ToRegionVid; use dataflow::move_paths::MoveData; use dataflow::FlowAtLocation; use dataflow::MaybeInitializedPlaces; +use either::Either; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::infer::canonical::QueryRegionConstraint; use rustc::infer::outlives::env::RegionBoundPairs; -use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; +use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; use rustc::mir::interpret::EvalErrorKind::BoundsCheck; use rustc::mir::tcx::PlaceTy; use rustc::mir::visit::{PlaceContext, Visitor}; @@ -44,14 +46,13 @@ use rustc::traits::{ObligationCause, PredicateObligations}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs, UnpackedKind}; use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::indexed_vec::IndexVec; use std::rc::Rc; use std::{fmt, iter}; use syntax_pos::{Span, DUMMY_SP}; use transform::{MirPass, MirSource}; -use either::Either; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; - macro_rules! span_mirbug { ($context:expr, $elem:expr, $($message:tt)*) => ({ $crate::borrow_check::nll::type_check::mirbug( @@ -127,6 +128,7 @@ pub(crate) fn type_check<'gcx, 'tcx>( let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body)); let mut constraints = MirTypeckRegionConstraints { placeholder_indices: PlaceholderIndices::default(), + placeholder_index_to_region: IndexVec::default(), liveness_constraints: LivenessValues::new(elements), outlives_constraints: ConstraintSet::default(), closure_bounds_mapping: Default::default(), @@ -738,8 +740,20 @@ crate struct MirTypeckResults<'tcx> { /// A collection of region constraints that must be satisfied for the /// program to be considered well-typed. crate struct MirTypeckRegionConstraints<'tcx> { + /// Maps from a `ty::Placeholder` to the corresponding + /// `PlaceholderIndex` bit that we will use for it. + /// + /// To keep everything in sync, do not insert this set + /// directly. Instead, use the `placeholder_region` helper. crate placeholder_indices: PlaceholderIndices, + /// Each time we add a placeholder to `placeholder_indices`, we + /// also create a corresponding "representative" region vid for + /// that wraps it. This vector tracks those. This way, when we + /// convert the same `ty::RePlaceholder(p)` twice, we can map to + /// the same underlying `RegionVid`. + crate placeholder_index_to_region: IndexVec<PlaceholderIndex, ty::Region<'tcx>>, + /// In general, the type-checker is not responsible for enforcing /// liveness constraints; this job falls to the region inferencer, /// which performs a liveness analysis. However, in some limited @@ -757,6 +771,25 @@ crate struct MirTypeckRegionConstraints<'tcx> { crate type_tests: Vec<TypeTest<'tcx>>, } +impl MirTypeckRegionConstraints<'tcx> { + fn placeholder_region( + &mut self, + infcx: &InferCtxt<'_, '_, 'tcx>, + placeholder: ty::Placeholder, + ) -> ty::Region<'tcx> { + let placeholder_index = self.placeholder_indices.insert(placeholder); + match self.placeholder_index_to_region.get(placeholder_index) { + Some(&v) => v, + None => { + let origin = NLLRegionVariableOrigin::Placeholder(placeholder); + let region = infcx.next_nll_region_var(origin); + self.placeholder_index_to_region.push(region); + region + } + } + } +} + /// The `Locations` type summarizes *where* region constraints are /// required to hold. Normally, this is at a particular point which /// created the obligation, but for constraints that the user gave, we @@ -886,15 +919,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { if let Some(ref mut borrowck_context) = self.borrowck_context { constraint_conversion::ConstraintConversion::new( - self.infcx.tcx, + self.infcx, borrowck_context.universal_regions, self.region_bound_pairs, self.implicit_region_bound, self.param_env, locations, category, - &mut borrowck_context.constraints.outlives_constraints, - &mut borrowck_context.constraints.type_tests, + &mut borrowck_context.constraints, ).convert_all(&data); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs index 5c699b5295d..b82efb29f6e 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs @@ -76,16 +76,20 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> { } fn next_existential_region_var(&mut self) -> ty::Region<'tcx> { - let origin = NLLRegionVariableOrigin::Existential; - self.infcx.next_nll_region_var(origin) + if let Some(_) = &mut self.borrowck_context { + let origin = NLLRegionVariableOrigin::Existential; + self.infcx.next_nll_region_var(origin) + } else { + self.infcx.tcx.types.re_erased + } } fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx> { - let origin = NLLRegionVariableOrigin::Placeholder(placeholder); if let Some(borrowck_context) = &mut self.borrowck_context { - borrowck_context.constraints.placeholder_indices.insert(placeholder); + borrowck_context.constraints.placeholder_region(self.infcx, placeholder) + } else { + self.infcx.tcx.types.re_erased } - self.infcx.next_nll_region_var(origin) } fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { |
