Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 52057 — inference variable #52731

Merged
merged 8 commits into from
Jul 31, 2018
13 changes: 13 additions & 0 deletions src/librustc/traits/query/type_op/custom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ fn scrape_region_constraints<'gcx, 'tcx, R>(
) -> Fallible<(R, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>)> {
let mut fulfill_cx = TraitEngine::new(infcx.tcx);
let dummy_body_id = ObligationCause::dummy().body_id;

// During NLL, we expect that nobody will register region
// obligations **except** as part of a custom type op (and, at the
// end of each custom type op, we scrape out the region
// obligations that resulted). So this vector should be empty on
// entry.
let pre_obligations = infcx.take_registered_region_obligations();
assert!(
pre_obligations.is_empty(),
"scrape_region_constraints: incoming region obligations = {:#?}",
pre_obligations,
);

let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
fulfill_cx.register_predicate_obligations(infcx, obligations);
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_mir/borrow_check/nll/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,14 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
None
};

let universal_regions = Rc::new(universal_regions);

let elements = &Rc::new(RegionValueElements::new(mir));

// Run the MIR type-checker.
let liveness_map = NllLivenessMap::compute(&mir);
let liveness = LivenessResults::compute(mir, &liveness_map);
let constraint_sets = type_check::type_check(
let (constraint_sets, universal_region_relations) = type_check::type_check(
infcx,
param_env,
mir,
Expand Down Expand Up @@ -153,6 +155,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
let mut regioncx = RegionInferenceContext::new(
var_origins,
universal_regions,
universal_region_relations,
mir,
outlives_constraints,
type_tests,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.universal_regions
.region_classification(region)
.unwrap();
let outlived_by = self.universal_regions.regions_outlived_by(region);
let outlived_by = self.universal_region_relations.regions_outlived_by(region);
writeln!(
out,
"| {r:rw$} | {c:cw$} | {ob}",
Expand Down
89 changes: 59 additions & 30 deletions src/librustc_mir/borrow_check/nll/region_infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use borrow_check::nll::constraints::{
ConstraintIndex, ConstraintSccIndex, ConstraintSet, OutlivesConstraint,
};
use borrow_check::nll::region_infer::values::{RegionElement, ToElementIndex};
use borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
use borrow_check::nll::type_check::Locations;
use rustc::hir::def_id::DefId;
use rustc::infer::canonical::QueryRegionConstraint;
Expand Down Expand Up @@ -80,8 +81,12 @@ pub struct RegionInferenceContext<'tcx> {
type_tests: Vec<TypeTest<'tcx>>,

/// Information about the universally quantified regions in scope
/// on this function and their (known) relations to one another.
/// on this function.
universal_regions: Rc<UniversalRegions<'tcx>>,

/// Information about how the universally quantified regions in
/// scope on this function relate to one another.
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
}

struct RegionDefinition<'tcx> {
Expand Down Expand Up @@ -206,15 +211,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// of constraints produced by the MIR type check.
pub(crate) fn new(
var_infos: VarInfos,
universal_regions: UniversalRegions<'tcx>,
universal_regions: Rc<UniversalRegions<'tcx>>,
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
_mir: &Mir<'tcx>,
outlives_constraints: ConstraintSet,
type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: LivenessValues<RegionVid>,
elements: &Rc<RegionValueElements>,
) -> Self {
let universal_regions = Rc::new(universal_regions);

// Create a RegionDefinition for each inference variable.
let definitions: IndexVec<_, _> = var_infos
.into_iter()
Expand Down Expand Up @@ -251,6 +255,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
scc_values,
type_tests,
universal_regions,
universal_region_relations,
};

result.init_free_and_bound_regions();
Expand Down Expand Up @@ -308,8 +313,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
for (external_name, variable) in self.universal_regions.named_universal_regions() {
debug!(
"init_universal_regions: region {:?} has external name {:?}",
variable,
external_name
variable, external_name
);
self.definitions[variable].external_name = Some(external_name);
}
Expand Down Expand Up @@ -419,10 +423,20 @@ impl<'tcx> RegionInferenceContext<'tcx> {
};

self.check_type_tests(
infcx, mir, mir_def_id, outlives_requirements.as_mut(), errors_buffer);
infcx,
mir,
mir_def_id,
outlives_requirements.as_mut(),
errors_buffer,
);

self.check_universal_regions(
infcx, mir, mir_def_id, outlives_requirements.as_mut(), errors_buffer);
infcx,
mir,
mir_def_id,
outlives_requirements.as_mut(),
errors_buffer,
);

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

Expand Down Expand Up @@ -581,13 +595,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
if let Some(lower_bound_region) = lower_bound_region {
let region_scope_tree = &tcx.region_scope_tree(mir_def_id);
let type_test_span = type_test.locations.span(mir);
infcx.construct_generic_bound_failure(
region_scope_tree,
type_test_span,
None,
type_test.generic_kind,
lower_bound_region,
).buffer(errors_buffer);
infcx
.construct_generic_bound_failure(
region_scope_tree,
type_test_span,
None,
type_test.generic_kind,
lower_bound_region,
)
.buffer(errors_buffer);
} else {
// FIXME. We should handle this case better. It
// indicates that we have e.g. some region variable
Expand All @@ -599,10 +615,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// iterating over the universal regions and reporting
// an error that multiple bounds are required.
let type_test_span = type_test.locations.span(mir);
tcx.sess.struct_span_err(
type_test_span,
&format!("`{}` does not live long enough", type_test.generic_kind,),
).buffer(errors_buffer);
tcx.sess
.struct_span_err(
type_test_span,
&format!("`{}` does not live long enough", type_test.generic_kind,),
)
.buffer(errors_buffer);
}
}
}
Expand Down Expand Up @@ -654,8 +672,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// region, which ensures it can be encoded in a `ClosureOutlivesRequirement`.
let lower_bound_plus = self.non_local_universal_upper_bound(*lower_bound);
assert!(self.universal_regions.is_universal_region(lower_bound_plus));
assert!(!self.universal_regions
.is_local_free_region(lower_bound_plus));
assert!(
!self
.universal_regions
.is_local_free_region(lower_bound_plus)
);

propagated_outlives_requirements.push(ClosureOutlivesRequirement {
subject,
Expand Down Expand Up @@ -768,7 +789,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {

// Grow further to get smallest universal region known to
// creator.
let non_local_lub = self.universal_regions.non_local_upper_bound(lub);
let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);

debug!(
"non_local_universal_upper_bound: non_local_lub={:?}",
Expand Down Expand Up @@ -804,7 +825,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let mut lub = self.universal_regions.fr_fn_body;
let r_scc = self.constraint_sccs.scc(r);
for ur in self.scc_values.universal_regions_outlived_by(r_scc) {
lub = self.universal_regions.postdom_upper_bound(lub, ur);
lub = self.universal_region_relations.postdom_upper_bound(lub, ur);
}

debug!("universal_upper_bound: r={:?} lub={:?}", r, lub);
Expand Down Expand Up @@ -872,7 +893,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.all(|r1| {
self.scc_values
.universal_regions_outlived_by(sup_region_scc)
.any(|r2| self.universal_regions.outlives(r2, r1))
.any(|r2| self.universal_region_relations.outlives(r2, r1))
});

if !universal_outlives {
Expand All @@ -887,7 +908,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
return true;
}

self.scc_values.contains_points(sup_region_scc, sub_region_scc)
self.scc_values
.contains_points(sup_region_scc, sub_region_scc)
}

/// Once regions have been propagated, this method is used to see
Expand Down Expand Up @@ -977,7 +999,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// (because `fr` includes `end(o)`).
for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) {
// If it is known that `fr: o`, carry on.
if self.universal_regions.outlives(longer_fr, shorter_fr) {
if self
.universal_region_relations
.outlives(longer_fr, shorter_fr)
{
continue;
}

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

// Grow `shorter_fr` until we find a non-local
// region. (We always will.) We'll call that
// `shorter_fr+` -- it's ever so slightly larger than
// `fr`.
let shorter_fr_plus = self.universal_regions.non_local_upper_bound(shorter_fr);
let shorter_fr_plus = self
.universal_region_relations
.non_local_upper_bound(shorter_fr);
debug!(
"check_universal_region: shorter_fr_plus={:?}",
shorter_fr_plus
Expand All @@ -1021,8 +1051,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Note: in this case, we use the unapproximated regions
// to report the error. This gives better error messages
// in some cases.
self.report_error(
mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
self.report_error(mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer);
}
}

Expand Down
Loading