Skip to content

Commit cc408fb

Browse files
committed
Auto merge of #52731 - nikomatsakis:issue-52057-inference-variable, r=pnkfelix
Issue 52057 — inference variable Break out the computation of universal region relations and do it during the typeck, where we can handle the resulting constraints that arise. r? @pnkfelix
2 parents 54628c8 + b9652ae commit cc408fb

File tree

10 files changed

+565
-331
lines changed

10 files changed

+565
-331
lines changed

src/librustc/traits/query/type_op/custom.rs

+13
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,19 @@ fn scrape_region_constraints<'gcx, 'tcx, R>(
7575
) -> Fallible<(R, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
7676
let mut fulfill_cx = TraitEngine::new(infcx.tcx);
7777
let dummy_body_id = ObligationCause::dummy().body_id;
78+
79+
// During NLL, we expect that nobody will register region
80+
// obligations **except** as part of a custom type op (and, at the
81+
// end of each custom type op, we scrape out the region
82+
// obligations that resulted). So this vector should be empty on
83+
// entry.
84+
let pre_obligations = infcx.take_registered_region_obligations();
85+
assert!(
86+
pre_obligations.is_empty(),
87+
"scrape_region_constraints: incoming region obligations = {:#?}",
88+
pre_obligations,
89+
);
90+
7891
let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
7992
debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
8093
fulfill_cx.register_predicate_obligations(infcx, obligations);

src/librustc_mir/borrow_check/nll/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,14 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
104104
None
105105
};
106106

107+
let universal_regions = Rc::new(universal_regions);
108+
107109
let elements = &Rc::new(RegionValueElements::new(mir));
108110

109111
// Run the MIR type-checker.
110112
let liveness_map = NllLivenessMap::compute(&mir);
111113
let liveness = LivenessResults::compute(mir, &liveness_map);
112-
let constraint_sets = type_check::type_check(
114+
let (constraint_sets, universal_region_relations) = type_check::type_check(
113115
infcx,
114116
param_env,
115117
mir,
@@ -153,6 +155,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
153155
let mut regioncx = RegionInferenceContext::new(
154156
var_origins,
155157
universal_regions,
158+
universal_region_relations,
156159
mir,
157160
outlives_constraints,
158161
type_tests,

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
3333
.universal_regions
3434
.region_classification(region)
3535
.unwrap();
36-
let outlived_by = self.universal_regions.regions_outlived_by(region);
36+
let outlived_by = self.universal_region_relations.regions_outlived_by(region);
3737
writeln!(
3838
out,
3939
"| {r:rw$} | {c:cw$} | {ob}",

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

+59-30
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use borrow_check::nll::constraints::{
1414
ConstraintIndex, ConstraintSccIndex, ConstraintSet, OutlivesConstraint,
1515
};
1616
use borrow_check::nll::region_infer::values::{RegionElement, ToElementIndex};
17+
use borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
1718
use borrow_check::nll::type_check::Locations;
1819
use rustc::hir::def_id::DefId;
1920
use rustc::infer::canonical::QueryRegionConstraint;
@@ -80,8 +81,12 @@ pub struct RegionInferenceContext<'tcx> {
8081
type_tests: Vec<TypeTest<'tcx>>,
8182

8283
/// Information about the universally quantified regions in scope
83-
/// on this function and their (known) relations to one another.
84+
/// on this function.
8485
universal_regions: Rc<UniversalRegions<'tcx>>,
86+
87+
/// Information about how the universally quantified regions in
88+
/// scope on this function relate to one another.
89+
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
8590
}
8691

8792
struct RegionDefinition<'tcx> {
@@ -206,15 +211,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
206211
/// of constraints produced by the MIR type check.
207212
pub(crate) fn new(
208213
var_infos: VarInfos,
209-
universal_regions: UniversalRegions<'tcx>,
214+
universal_regions: Rc<UniversalRegions<'tcx>>,
215+
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
210216
_mir: &Mir<'tcx>,
211217
outlives_constraints: ConstraintSet,
212218
type_tests: Vec<TypeTest<'tcx>>,
213219
liveness_constraints: LivenessValues<RegionVid>,
214220
elements: &Rc<RegionValueElements>,
215221
) -> Self {
216-
let universal_regions = Rc::new(universal_regions);
217-
218222
// Create a RegionDefinition for each inference variable.
219223
let definitions: IndexVec<_, _> = var_infos
220224
.into_iter()
@@ -251,6 +255,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
251255
scc_values,
252256
type_tests,
253257
universal_regions,
258+
universal_region_relations,
254259
};
255260

256261
result.init_free_and_bound_regions();
@@ -308,8 +313,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
308313
for (external_name, variable) in self.universal_regions.named_universal_regions() {
309314
debug!(
310315
"init_universal_regions: region {:?} has external name {:?}",
311-
variable,
312-
external_name
316+
variable, external_name
313317
);
314318
self.definitions[variable].external_name = Some(external_name);
315319
}
@@ -419,10 +423,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
419423
};
420424

421425
self.check_type_tests(
422-
infcx, mir, mir_def_id, outlives_requirements.as_mut(), errors_buffer);
426+
infcx,
427+
mir,
428+
mir_def_id,
429+
outlives_requirements.as_mut(),
430+
errors_buffer,
431+
);
423432

424433
self.check_universal_regions(
425-
infcx, mir, mir_def_id, outlives_requirements.as_mut(), errors_buffer);
434+
infcx,
435+
mir,
436+
mir_def_id,
437+
outlives_requirements.as_mut(),
438+
errors_buffer,
439+
);
426440

427441
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
428442

@@ -581,13 +595,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
581595
if let Some(lower_bound_region) = lower_bound_region {
582596
let region_scope_tree = &tcx.region_scope_tree(mir_def_id);
583597
let type_test_span = type_test.locations.span(mir);
584-
infcx.construct_generic_bound_failure(
585-
region_scope_tree,
586-
type_test_span,
587-
None,
588-
type_test.generic_kind,
589-
lower_bound_region,
590-
).buffer(errors_buffer);
598+
infcx
599+
.construct_generic_bound_failure(
600+
region_scope_tree,
601+
type_test_span,
602+
None,
603+
type_test.generic_kind,
604+
lower_bound_region,
605+
)
606+
.buffer(errors_buffer);
591607
} else {
592608
// FIXME. We should handle this case better. It
593609
// indicates that we have e.g. some region variable
@@ -599,10 +615,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
599615
// iterating over the universal regions and reporting
600616
// an error that multiple bounds are required.
601617
let type_test_span = type_test.locations.span(mir);
602-
tcx.sess.struct_span_err(
603-
type_test_span,
604-
&format!("`{}` does not live long enough", type_test.generic_kind,),
605-
).buffer(errors_buffer);
618+
tcx.sess
619+
.struct_span_err(
620+
type_test_span,
621+
&format!("`{}` does not live long enough", type_test.generic_kind,),
622+
)
623+
.buffer(errors_buffer);
606624
}
607625
}
608626
}
@@ -654,8 +672,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
654672
// region, which ensures it can be encoded in a `ClosureOutlivesRequirement`.
655673
let lower_bound_plus = self.non_local_universal_upper_bound(*lower_bound);
656674
assert!(self.universal_regions.is_universal_region(lower_bound_plus));
657-
assert!(!self.universal_regions
658-
.is_local_free_region(lower_bound_plus));
675+
assert!(
676+
!self
677+
.universal_regions
678+
.is_local_free_region(lower_bound_plus)
679+
);
659680

660681
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
661682
subject,
@@ -768,7 +789,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
768789

769790
// Grow further to get smallest universal region known to
770791
// creator.
771-
let non_local_lub = self.universal_regions.non_local_upper_bound(lub);
792+
let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);
772793

773794
debug!(
774795
"non_local_universal_upper_bound: non_local_lub={:?}",
@@ -804,7 +825,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
804825
let mut lub = self.universal_regions.fr_fn_body;
805826
let r_scc = self.constraint_sccs.scc(r);
806827
for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
807-
lub = self.universal_regions.postdom_upper_bound(lub, ur);
828+
lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
808829
}
809830

810831
debug!("universal_upper_bound: r={:?} lub={:?}", r, lub);
@@ -872,7 +893,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
872893
.all(|r1| {
873894
self.scc_values
874895
.universal_regions_outlived_by(sup_region_scc)
875-
.any(|r2| self.universal_regions.outlives(r2, r1))
896+
.any(|r2| self.universal_region_relations.outlives(r2, r1))
876897
});
877898

878899
if !universal_outlives {
@@ -887,7 +908,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
887908
return true;
888909
}
889910

890-
self.scc_values.contains_points(sup_region_scc, sub_region_scc)
911+
self.scc_values
912+
.contains_points(sup_region_scc, sub_region_scc)
891913
}
892914

893915
/// Once regions have been propagated, this method is used to see
@@ -977,7 +999,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
977999
// (because `fr` includes `end(o)`).
9781000
for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) {
9791001
// If it is known that `fr: o`, carry on.
980-
if self.universal_regions.outlives(longer_fr, shorter_fr) {
1002+
if self
1003+
.universal_region_relations
1004+
.outlives(longer_fr, shorter_fr)
1005+
{
9811006
continue;
9821007
}
9831008

@@ -991,14 +1016,19 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9911016
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
9921017
// Shrink `fr` until we find a non-local region (if we do).
9931018
// We'll call that `fr-` -- it's ever so slightly smaller than `fr`.
994-
if let Some(fr_minus) = self.universal_regions.non_local_lower_bound(longer_fr) {
1019+
if let Some(fr_minus) = self
1020+
.universal_region_relations
1021+
.non_local_lower_bound(longer_fr)
1022+
{
9951023
debug!("check_universal_region: fr_minus={:?}", fr_minus);
9961024

9971025
// Grow `shorter_fr` until we find a non-local
9981026
// region. (We always will.) We'll call that
9991027
// `shorter_fr+` -- it's ever so slightly larger than
10001028
// `fr`.
1001-
let shorter_fr_plus = self.universal_regions.non_local_upper_bound(shorter_fr);
1029+
let shorter_fr_plus = self
1030+
.universal_region_relations
1031+
.non_local_upper_bound(shorter_fr);
10021032
debug!(
10031033
"check_universal_region: shorter_fr_plus={:?}",
10041034
shorter_fr_plus
@@ -1021,8 +1051,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
10211051
// Note: in this case, we use the unapproximated regions
10221052
// to report the error. This gives better error messages
10231053
// in some cases.
1024-
self.report_error(
1025-
mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
1054+
self.report_error(mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
10261055
}
10271056
}
10281057

0 commit comments

Comments
 (0)