Skip to content

Commit 784746f

Browse files
committed
convert placeholder region vids in NLL mode as we see them
1 parent 018c515 commit 784746f

File tree

7 files changed

+88
-38
lines changed

7 files changed

+88
-38
lines changed

src/librustc_mir/borrow_check/nll/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
134134
let var_origins = infcx.take_region_var_origins();
135135
let MirTypeckRegionConstraints {
136136
placeholder_indices,
137+
placeholder_index_to_region: _,
137138
mut liveness_constraints,
138139
outlives_constraints,
139140
closure_bounds_mapping,

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
594594
// Finds some region R such that `fr1: R` and `R` is live at
595595
// `elem`.
596596
crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
597+
debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
597598
// Find all paths
598599
let (_path, r) =
599600
self.find_constraint_paths_between_regions(fr1, |r| {

src/librustc_mir/borrow_check/nll/region_infer/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
12261226
);
12271227

12281228
let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
1229+
debug!(
1230+
"check_bound_universal_region: longer_fr_scc={:?}",
1231+
longer_fr_scc,
1232+
);
12291233

12301234
// If we have some bound universal region `'a`, then the only
12311235
// elements it can contain is itself -- we don't know anything
@@ -1242,6 +1246,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
12421246
Some(v) => v,
12431247
None => return,
12441248
};
1249+
debug!("check_bound_universal_region: error_element = {:?}", error_element);
12451250

12461251
// Find the region that introduced this `error_element`.
12471252
let error_region = match error_element {

src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,54 +8,54 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
11+
use borrow_check::nll::constraints::OutlivesConstraint;
1212
use borrow_check::nll::region_infer::TypeTest;
13-
use borrow_check::nll::type_check::Locations;
13+
use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
1414
use borrow_check::nll::universal_regions::UniversalRegions;
15+
use borrow_check::nll::ToRegionVid;
1516
use rustc::infer::canonical::QueryRegionConstraint;
1617
use rustc::infer::outlives::env::RegionBoundPairs;
1718
use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
1819
use rustc::infer::region_constraints::{GenericKind, VerifyBound};
19-
use rustc::infer::{self, SubregionOrigin};
20+
use rustc::infer::{self, InferCtxt, SubregionOrigin};
2021
use rustc::mir::ConstraintCategory;
2122
use rustc::ty::subst::UnpackedKind;
2223
use rustc::ty::{self, TyCtxt};
2324
use syntax_pos::DUMMY_SP;
2425

2526
crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
27+
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
2628
tcx: TyCtxt<'a, 'gcx, 'tcx>,
2729
universal_regions: &'a UniversalRegions<'tcx>,
2830
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
2931
implicit_region_bound: Option<ty::Region<'tcx>>,
3032
param_env: ty::ParamEnv<'tcx>,
3133
locations: Locations,
3234
category: ConstraintCategory,
33-
outlives_constraints: &'a mut ConstraintSet,
34-
type_tests: &'a mut Vec<TypeTest<'tcx>>,
35+
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
3536
}
3637

3738
impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
3839
crate fn new(
39-
tcx: TyCtxt<'a, 'gcx, 'tcx>,
40+
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
4041
universal_regions: &'a UniversalRegions<'tcx>,
4142
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
4243
implicit_region_bound: Option<ty::Region<'tcx>>,
4344
param_env: ty::ParamEnv<'tcx>,
4445
locations: Locations,
4546
category: ConstraintCategory,
46-
outlives_constraints: &'a mut ConstraintSet,
47-
type_tests: &'a mut Vec<TypeTest<'tcx>>,
47+
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
4848
) -> Self {
4949
Self {
50-
tcx,
50+
infcx,
51+
tcx: infcx.tcx,
5152
universal_regions,
5253
region_bound_pairs,
5354
implicit_region_bound,
5455
param_env,
5556
locations,
5657
category,
57-
outlives_constraints,
58-
type_tests,
58+
constraints,
5959
}
6060
}
6161

@@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
113113
}
114114

115115
fn verify_to_type_test(
116-
&self,
116+
&mut self,
117117
generic_kind: GenericKind<'tcx>,
118118
region: ty::Region<'tcx>,
119119
verify_bound: VerifyBound<'tcx>,
@@ -128,22 +128,30 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
128128
}
129129
}
130130

131-
fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
132-
self.universal_regions.to_region_vid(r)
131+
fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
132+
if let ty::RePlaceholder(placeholder) = r {
133+
self.constraints
134+
.placeholder_region(self.infcx, *placeholder)
135+
.to_region_vid()
136+
} else {
137+
self.universal_regions.to_region_vid(r)
138+
}
133139
}
134140

135141
fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
136-
self.outlives_constraints.push(OutlivesConstraint {
137-
locations: self.locations,
138-
category: self.category,
139-
sub,
140-
sup,
141-
});
142+
self.constraints
143+
.outlives_constraints
144+
.push(OutlivesConstraint {
145+
locations: self.locations,
146+
category: self.category,
147+
sub,
148+
sup,
149+
});
142150
}
143151

144152
fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
145153
debug!("add_type_test(type_test={:?})", type_test);
146-
self.type_tests.push(type_test);
154+
self.constraints.type_tests.push(type_test);
147155
}
148156
}
149157

@@ -156,8 +164,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx>
156164
a: ty::Region<'tcx>,
157165
b: ty::Region<'tcx>,
158166
) {
159-
let b = self.universal_regions.to_region_vid(b);
160-
let a = self.universal_regions.to_region_vid(a);
167+
let b = self.to_region_vid(b);
168+
let a = self.to_region_vid(a);
161169
self.add_outlives(b, a);
162170
}
163171

src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,15 +271,14 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
271271

272272
for data in constraint_sets {
273273
constraint_conversion::ConstraintConversion::new(
274-
self.infcx.tcx,
274+
self.infcx,
275275
&self.universal_regions,
276276
&self.region_bound_pairs,
277277
self.implicit_region_bound,
278278
self.param_env,
279279
Locations::All(DUMMY_SP),
280280
ConstraintCategory::Internal,
281-
&mut self.constraints.outlives_constraints,
282-
&mut self.constraints.type_tests,
281+
&mut self.constraints,
283282
).convert_all(&data);
284283
}
285284

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use borrow_check::location::LocationTable;
1616
use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
1717
use borrow_check::nll::facts::AllFacts;
1818
use borrow_check::nll::region_infer::values::LivenessValues;
19+
use borrow_check::nll::region_infer::values::PlaceholderIndex;
1920
use borrow_check::nll::region_infer::values::PlaceholderIndices;
2021
use borrow_check::nll::region_infer::values::RegionValueElements;
2122
use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
@@ -28,11 +29,12 @@ use borrow_check::nll::ToRegionVid;
2829
use dataflow::move_paths::MoveData;
2930
use dataflow::FlowAtLocation;
3031
use dataflow::MaybeInitializedPlaces;
32+
use either::Either;
3133
use rustc::hir;
3234
use rustc::hir::def_id::DefId;
3335
use rustc::infer::canonical::QueryRegionConstraint;
3436
use rustc::infer::outlives::env::RegionBoundPairs;
35-
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
37+
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
3638
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
3739
use rustc::mir::tcx::PlaceTy;
3840
use rustc::mir::visit::{PlaceContext, Visitor};
@@ -44,14 +46,13 @@ use rustc::traits::{ObligationCause, PredicateObligations};
4446
use rustc::ty::fold::TypeFoldable;
4547
use rustc::ty::subst::{Subst, Substs, UnpackedKind};
4648
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
49+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
50+
use rustc_data_structures::indexed_vec::IndexVec;
4751
use std::rc::Rc;
4852
use std::{fmt, iter};
4953
use syntax_pos::{Span, DUMMY_SP};
5054
use transform::{MirPass, MirSource};
5155

52-
use either::Either;
53-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
54-
5556
macro_rules! span_mirbug {
5657
($context:expr, $elem:expr, $($message:tt)*) => ({
5758
$crate::borrow_check::nll::type_check::mirbug(
@@ -127,6 +128,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
127128
let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
128129
let mut constraints = MirTypeckRegionConstraints {
129130
placeholder_indices: PlaceholderIndices::default(),
131+
placeholder_index_to_region: IndexVec::default(),
130132
liveness_constraints: LivenessValues::new(elements),
131133
outlives_constraints: ConstraintSet::default(),
132134
closure_bounds_mapping: Default::default(),
@@ -738,8 +740,20 @@ crate struct MirTypeckResults<'tcx> {
738740
/// A collection of region constraints that must be satisfied for the
739741
/// program to be considered well-typed.
740742
crate struct MirTypeckRegionConstraints<'tcx> {
743+
/// Maps from a `ty::Placeholder` to the corresponding
744+
/// `PlaceholderIndex` bit that we will use for it.
745+
///
746+
/// To keep everything in sync, do not insert this set
747+
/// directly. Instead, use the `placeholder_region` helper.
741748
crate placeholder_indices: PlaceholderIndices,
742749

750+
/// Each time we add a placeholder to `placeholder_indices`, we
751+
/// also create a corresponding "representative" region vid for
752+
/// that wraps it. This vector tracks those. This way, when we
753+
/// convert the same `ty::RePlaceholder(p)` twice, we can map to
754+
/// the same underlying `RegionVid`.
755+
crate placeholder_index_to_region: IndexVec<PlaceholderIndex, ty::Region<'tcx>>,
756+
743757
/// In general, the type-checker is not responsible for enforcing
744758
/// liveness constraints; this job falls to the region inferencer,
745759
/// which performs a liveness analysis. However, in some limited
@@ -757,6 +771,25 @@ crate struct MirTypeckRegionConstraints<'tcx> {
757771
crate type_tests: Vec<TypeTest<'tcx>>,
758772
}
759773

774+
impl MirTypeckRegionConstraints<'tcx> {
775+
fn placeholder_region(
776+
&mut self,
777+
infcx: &InferCtxt<'_, '_, 'tcx>,
778+
placeholder: ty::Placeholder,
779+
) -> ty::Region<'tcx> {
780+
let placeholder_index = self.placeholder_indices.insert(placeholder);
781+
match self.placeholder_index_to_region.get(placeholder_index) {
782+
Some(&v) => v,
783+
None => {
784+
let origin = NLLRegionVariableOrigin::Placeholder(placeholder);
785+
let region = infcx.next_nll_region_var(origin);
786+
self.placeholder_index_to_region.push(region);
787+
region
788+
}
789+
}
790+
}
791+
}
792+
760793
/// The `Locations` type summarizes *where* region constraints are
761794
/// required to hold. Normally, this is at a particular point which
762795
/// created the obligation, but for constraints that the user gave, we
@@ -886,15 +919,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
886919

887920
if let Some(ref mut borrowck_context) = self.borrowck_context {
888921
constraint_conversion::ConstraintConversion::new(
889-
self.infcx.tcx,
922+
self.infcx,
890923
borrowck_context.universal_regions,
891924
self.region_bound_pairs,
892925
self.implicit_region_bound,
893926
self.param_env,
894927
locations,
895928
category,
896-
&mut borrowck_context.constraints.outlives_constraints,
897-
&mut borrowck_context.constraints.type_tests,
929+
&mut borrowck_context.constraints,
898930
).convert_all(&data);
899931
}
900932
}

src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,16 +76,20 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> {
7676
}
7777

7878
fn next_existential_region_var(&mut self) -> ty::Region<'tcx> {
79-
let origin = NLLRegionVariableOrigin::Existential;
80-
self.infcx.next_nll_region_var(origin)
79+
if let Some(_) = &mut self.borrowck_context {
80+
let origin = NLLRegionVariableOrigin::Existential;
81+
self.infcx.next_nll_region_var(origin)
82+
} else {
83+
self.infcx.tcx.types.re_erased
84+
}
8185
}
8286

8387
fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx> {
84-
let origin = NLLRegionVariableOrigin::Placeholder(placeholder);
8588
if let Some(borrowck_context) = &mut self.borrowck_context {
86-
borrowck_context.constraints.placeholder_indices.insert(placeholder);
89+
borrowck_context.constraints.placeholder_region(self.infcx, placeholder)
90+
} else {
91+
self.infcx.tcx.types.re_erased
8792
}
88-
self.infcx.next_nll_region_var(origin)
8993
}
9094

9195
fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {

0 commit comments

Comments
 (0)