|
|
|
@@ -1,20 +1,23 @@
|
|
|
|
|
use super::universal_regions::UniversalRegions;
|
|
|
|
|
use crate::borrow_check::nll::constraints::graph::NormalConstraintGraph;
|
|
|
|
|
use crate::borrow_check::nll::constraints::{ConstraintSccIndex, OutlivesConstraintSet, OutlivesConstraint};
|
|
|
|
|
use crate::borrow_check::nll::constraints::{
|
|
|
|
|
ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet,
|
|
|
|
|
};
|
|
|
|
|
use crate::borrow_check::nll::pick_constraints::PickConstraintSet;
|
|
|
|
|
use crate::borrow_check::nll::region_infer::values::{
|
|
|
|
|
PlaceholderIndices, RegionElement, ToElementIndex
|
|
|
|
|
PlaceholderIndices, RegionElement, ToElementIndex,
|
|
|
|
|
};
|
|
|
|
|
use crate::borrow_check::Upvar;
|
|
|
|
|
use crate::borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
|
|
|
|
|
use crate::borrow_check::nll::type_check::Locations;
|
|
|
|
|
use crate::borrow_check::Upvar;
|
|
|
|
|
use rustc::hir::def_id::DefId;
|
|
|
|
|
use rustc::infer::canonical::QueryOutlivesConstraint;
|
|
|
|
|
use rustc::infer::opaque_types;
|
|
|
|
|
use rustc::infer::region_constraints::{GenericKind, VarInfos, VerifyBound};
|
|
|
|
|
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin};
|
|
|
|
|
use rustc::mir::{
|
|
|
|
|
ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
|
|
|
|
|
ConstraintCategory, Local, Location, Body,
|
|
|
|
|
Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
|
|
|
|
|
ConstraintCategory, Local, Location,
|
|
|
|
|
};
|
|
|
|
|
use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
|
|
|
|
|
use rustc::util::common::{self, ErrorReported};
|
|
|
|
@@ -61,6 +64,9 @@ pub struct RegionInferenceContext<'tcx> {
|
|
|
|
|
/// compute the values of each region.
|
|
|
|
|
constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>,
|
|
|
|
|
|
|
|
|
|
/// The "pick R0 from [R1..Rn]" constraints, indexed by SCC.
|
|
|
|
|
pick_constraints: Rc<PickConstraintSet<'tcx, ConstraintSccIndex>>,
|
|
|
|
|
|
|
|
|
|
/// Map closure bounds to a `Span` that should be used for error reporting.
|
|
|
|
|
closure_bounds_mapping:
|
|
|
|
|
FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
|
|
|
|
@@ -188,7 +194,7 @@ pub(crate) fn new(
|
|
|
|
|
universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
|
|
|
|
|
_body: &Body<'tcx>,
|
|
|
|
|
outlives_constraints: OutlivesConstraintSet,
|
|
|
|
|
pick_constraints: PickConstraintSet<'tcx, RegionVid>,
|
|
|
|
|
pick_constraints_in: PickConstraintSet<'tcx, RegionVid>,
|
|
|
|
|
closure_bounds_mapping: FxHashMap<
|
|
|
|
|
Location,
|
|
|
|
|
FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
|
|
|
|
@@ -220,9 +226,7 @@ pub(crate) fn new(
|
|
|
|
|
|
|
|
|
|
let scc_representatives = Self::compute_scc_representatives(&constraint_sccs, &definitions);
|
|
|
|
|
|
|
|
|
|
let _pick_constraints_scc = pick_constraints.into_mapped( // TODO
|
|
|
|
|
|r| constraint_sccs.scc(r),
|
|
|
|
|
);
|
|
|
|
|
let pick_constraints = Rc::new(pick_constraints_in.into_mapped(|r| constraint_sccs.scc(r)));
|
|
|
|
|
|
|
|
|
|
let mut result = Self {
|
|
|
|
|
definitions,
|
|
|
|
@@ -230,6 +234,7 @@ pub(crate) fn new(
|
|
|
|
|
constraints,
|
|
|
|
|
constraint_graph,
|
|
|
|
|
constraint_sccs,
|
|
|
|
|
pick_constraints,
|
|
|
|
|
closure_bounds_mapping,
|
|
|
|
|
scc_universes,
|
|
|
|
|
scc_representatives,
|
|
|
|
@@ -347,9 +352,7 @@ fn init_free_and_bound_regions(&mut self) {
|
|
|
|
|
debug!(
|
|
|
|
|
"init_free_and_bound_regions: placeholder {:?} is \
|
|
|
|
|
not compatible with universe {:?} of its SCC {:?}",
|
|
|
|
|
placeholder,
|
|
|
|
|
scc_universe,
|
|
|
|
|
scc,
|
|
|
|
|
placeholder, scc_universe, scc,
|
|
|
|
|
);
|
|
|
|
|
self.add_incompatible_universe(scc);
|
|
|
|
|
}
|
|
|
|
@@ -434,11 +437,8 @@ fn solve_inner(
|
|
|
|
|
// to store those. Otherwise, we'll pass in `None` to the
|
|
|
|
|
// functions below, which will trigger them to report errors
|
|
|
|
|
// eagerly.
|
|
|
|
|
let mut outlives_requirements = if infcx.tcx.is_closure(mir_def_id) {
|
|
|
|
|
Some(vec![])
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
|
let mut outlives_requirements =
|
|
|
|
|
if infcx.tcx.is_closure(mir_def_id) { Some(vec![]) } else { None };
|
|
|
|
|
|
|
|
|
|
self.check_type_tests(
|
|
|
|
|
infcx,
|
|
|
|
@@ -457,16 +457,15 @@ fn solve_inner(
|
|
|
|
|
errors_buffer,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
self.check_pick_constraints(infcx, mir_def_id, errors_buffer);
|
|
|
|
|
|
|
|
|
|
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
|
|
|
|
|
|
|
|
|
|
if outlives_requirements.is_empty() {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
let num_external_vids = self.universal_regions.num_global_and_external_regions();
|
|
|
|
|
Some(ClosureRegionRequirements {
|
|
|
|
|
num_external_vids,
|
|
|
|
|
outlives_requirements,
|
|
|
|
|
})
|
|
|
|
|
Some(ClosureRegionRequirements { num_external_vids, outlives_requirements })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -496,6 +495,8 @@ fn propagate_constraints(&mut self, _body: &Body<'tcx>) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes the value of the SCC `scc_a` if it has not already
|
|
|
|
|
/// been computed. The `visited` parameter is a bitset
|
|
|
|
|
#[inline]
|
|
|
|
|
fn propagate_constraint_sccs_if_new(
|
|
|
|
|
&mut self,
|
|
|
|
@@ -507,6 +508,10 @@ fn propagate_constraint_sccs_if_new(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes the value of the SCC `scc_a`, which has not yet been
|
|
|
|
|
/// computed. This works by first computing all successors of the
|
|
|
|
|
/// SCC (if they haven't been computed already) and then unioning
|
|
|
|
|
/// together their elements.
|
|
|
|
|
fn propagate_constraint_sccs_new(
|
|
|
|
|
&mut self,
|
|
|
|
|
scc_a: ConstraintSccIndex,
|
|
|
|
@@ -516,10 +521,7 @@ fn propagate_constraint_sccs_new(
|
|
|
|
|
|
|
|
|
|
// Walk each SCC `B` such that `A: B`...
|
|
|
|
|
for &scc_b in constraint_sccs.successors(scc_a) {
|
|
|
|
|
debug!(
|
|
|
|
|
"propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}",
|
|
|
|
|
scc_a, scc_b
|
|
|
|
|
);
|
|
|
|
|
debug!("propagate_constraint_sccs: scc_a = {:?} scc_b = {:?}", scc_a, scc_b);
|
|
|
|
|
|
|
|
|
|
// ...compute the value of `B`...
|
|
|
|
|
self.propagate_constraint_sccs_if_new(scc_b, visited);
|
|
|
|
@@ -537,6 +539,12 @@ fn propagate_constraint_sccs_new(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now take pick constraints into account
|
|
|
|
|
let pick_constraints = self.pick_constraints.clone();
|
|
|
|
|
for p_c_i in pick_constraints.indices(scc_a) {
|
|
|
|
|
self.apply_pick_constraint(scc_a, pick_constraints.option_regions(p_c_i));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug!(
|
|
|
|
|
"propagate_constraint_sccs: scc_a = {:?} has value {:?}",
|
|
|
|
|
scc_a,
|
|
|
|
@@ -544,6 +552,114 @@ fn propagate_constraint_sccs_new(
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Invoked for each `pick R0 from [R1..Rn]` constraint.
|
|
|
|
|
///
|
|
|
|
|
/// `scc` is the SCC containing R0, and `option_regions` are the
|
|
|
|
|
/// `R1..Rn` regions -- they are always known to be universal
|
|
|
|
|
/// regions (and if that's not true, we just don't attempt to
|
|
|
|
|
/// enforce the constraint).
|
|
|
|
|
///
|
|
|
|
|
/// The current value of `scc` at the time the method is invoked
|
|
|
|
|
/// is considered a *lower bound*. If possible, we will modify
|
|
|
|
|
/// the constraint to set it equal to one of the option regions.
|
|
|
|
|
/// If we make any changes, returns true, else false.
|
|
|
|
|
fn apply_pick_constraint(
|
|
|
|
|
&mut self,
|
|
|
|
|
scc: ConstraintSccIndex,
|
|
|
|
|
option_regions: &[ty::RegionVid],
|
|
|
|
|
) -> bool {
|
|
|
|
|
debug!("apply_pick_constraint(scc={:?}, option_regions={:#?})", scc, option_regions,);
|
|
|
|
|
|
|
|
|
|
if let Some(uh_oh) =
|
|
|
|
|
option_regions.iter().find(|&&r| !self.universal_regions.is_universal_region(r))
|
|
|
|
|
{
|
|
|
|
|
debug!("apply_pick_constraint: option region `{:?}` is not a universal region", uh_oh);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a mutable vector of the options. We'll try to winnow
|
|
|
|
|
// them down.
|
|
|
|
|
let mut option_regions: Vec<ty::RegionVid> = option_regions.to_vec();
|
|
|
|
|
|
|
|
|
|
// The 'pick-region' in a pick-constraint is part of the
|
|
|
|
|
// hidden type, which must be in the root universe. Therefore,
|
|
|
|
|
// it cannot have any placeholders in its value.
|
|
|
|
|
assert!(self.scc_universes[scc] == ty::UniverseIndex::ROOT);
|
|
|
|
|
debug_assert!(
|
|
|
|
|
self.scc_values.placeholders_contained_in(scc).next().is_none(),
|
|
|
|
|
"scc {:?} in a pick-constraint has placeholder value: {:?}",
|
|
|
|
|
scc,
|
|
|
|
|
self.scc_values.region_value_str(scc),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// The existing value for `scc` is a lower-bound. This will
|
|
|
|
|
// consist of some set {P} + {LB} of points {P} and
|
|
|
|
|
// lower-bound free regions {LB}. As each option region O is a
|
|
|
|
|
// free region, it will outlive the points. But we can only
|
|
|
|
|
// consider the option O if O: LB.
|
|
|
|
|
option_regions.retain(|&o_r| {
|
|
|
|
|
self.scc_values
|
|
|
|
|
.universal_regions_outlived_by(scc)
|
|
|
|
|
.all(|lb| self.universal_region_relations.outlives(o_r, lb))
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Now find all the *upper bounds* -- that is, each UB is a free
|
|
|
|
|
// region that must outlive pick region R0 (`UB: R0`). Therefore,
|
|
|
|
|
// we need only keep an option O if `UB: O`.
|
|
|
|
|
//
|
|
|
|
|
// TODO -- need to implement the reverse graph construction for this
|
|
|
|
|
//
|
|
|
|
|
// let mut upper_bounds = ...;
|
|
|
|
|
// option_regions.retain(|&o_r| {
|
|
|
|
|
// upper_bounds
|
|
|
|
|
// .all(|ub| self.universal_region_relations.outlives(
|
|
|
|
|
// ub,
|
|
|
|
|
// o_r,
|
|
|
|
|
// })
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// If we ruled everything out, we're done.
|
|
|
|
|
if option_regions.is_empty() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Otherwise, we need to find the minimum option, if any, and take that.
|
|
|
|
|
debug!("apply_pick_constraint: option_regions remaining are {:#?}", option_regions);
|
|
|
|
|
let min = |r1: ty::RegionVid, r2: ty::RegionVid| -> Option<ty::RegionVid> {
|
|
|
|
|
let r1_outlives_r2 = self.universal_region_relations.outlives(r1, r2);
|
|
|
|
|
let r2_outlives_r1 = self.universal_region_relations.outlives(r2, r1);
|
|
|
|
|
if r1_outlives_r2 && r2_outlives_r1 {
|
|
|
|
|
Some(r1.min(r2))
|
|
|
|
|
} else if r1_outlives_r2 {
|
|
|
|
|
Some(r2)
|
|
|
|
|
} else if r2_outlives_r1 {
|
|
|
|
|
Some(r1)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let mut best_option = option_regions[0];
|
|
|
|
|
for &other_option in &option_regions[1..] {
|
|
|
|
|
debug!(
|
|
|
|
|
"apply_pick_constraint: best_option={:?} other_option={:?}",
|
|
|
|
|
best_option, other_option,
|
|
|
|
|
);
|
|
|
|
|
match min(best_option, other_option) {
|
|
|
|
|
Some(m) => best_option = m,
|
|
|
|
|
None => {
|
|
|
|
|
debug!(
|
|
|
|
|
"apply_pick_constraint: {:?} and {:?} are incomparable --> no best choice",
|
|
|
|
|
best_option, other_option,
|
|
|
|
|
);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug!("apply_pick_constraint: best_choice={:?}", best_option);
|
|
|
|
|
self.scc_values.add_element(scc, best_option)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns `true` if all the elements in the value of `scc_b` are nameable
|
|
|
|
|
/// in `scc_a`. Used during constraint propagation, and only once
|
|
|
|
|
/// the value of `scc_b` has been computed.
|
|
|
|
@@ -560,9 +676,7 @@ fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccInd
|
|
|
|
|
// Otherwise, we have to iterate over the universe elements in
|
|
|
|
|
// B's value, and check whether all of them are nameable
|
|
|
|
|
// from universe_a
|
|
|
|
|
self.scc_values
|
|
|
|
|
.placeholders_contained_in(scc_b)
|
|
|
|
|
.all(|p| universe_a.can_name(p.universe))
|
|
|
|
|
self.scc_values.placeholders_contained_in(scc_b).all(|p| universe_a.can_name(p.universe))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Extend `scc` so that it can outlive some placeholder region
|
|
|
|
@@ -737,12 +851,7 @@ fn try_promote_type_test(
|
|
|
|
|
) -> bool {
|
|
|
|
|
let tcx = infcx.tcx;
|
|
|
|
|
|
|
|
|
|
let TypeTest {
|
|
|
|
|
generic_kind,
|
|
|
|
|
lower_bound,
|
|
|
|
|
locations,
|
|
|
|
|
verify_bound: _,
|
|
|
|
|
} = type_test;
|
|
|
|
|
let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
|
|
|
|
|
|
|
|
|
|
let generic_ty = generic_kind.to_ty(tcx);
|
|
|
|
|
let subject = match self.try_promote_type_test_subject(infcx, generic_ty) {
|
|
|
|
@@ -892,11 +1001,7 @@ fn try_promote_type_test_subject(
|
|
|
|
|
/// except that it converts further takes the non-local upper
|
|
|
|
|
/// bound of `'y`, so that the final result is non-local.
|
|
|
|
|
fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
|
|
|
|
|
debug!(
|
|
|
|
|
"non_local_universal_upper_bound(r={:?}={})",
|
|
|
|
|
r,
|
|
|
|
|
self.region_value_str(r)
|
|
|
|
|
);
|
|
|
|
|
debug!("non_local_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
|
|
|
|
|
|
|
|
|
|
let lub = self.universal_upper_bound(r);
|
|
|
|
|
|
|
|
|
@@ -904,10 +1009,7 @@ fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
|
|
|
|
|
// creator.
|
|
|
|
|
let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);
|
|
|
|
|
|
|
|
|
|
debug!(
|
|
|
|
|
"non_local_universal_upper_bound: non_local_lub={:?}",
|
|
|
|
|
non_local_lub
|
|
|
|
|
);
|
|
|
|
|
debug!("non_local_universal_upper_bound: non_local_lub={:?}", non_local_lub);
|
|
|
|
|
|
|
|
|
|
non_local_lub
|
|
|
|
|
}
|
|
|
|
@@ -927,11 +1029,7 @@ fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
|
|
|
|
|
/// - For each `end('x)` element in `'r`, compute the mutual LUB, yielding
|
|
|
|
|
/// a result `'y`.
|
|
|
|
|
fn universal_upper_bound(&self, r: RegionVid) -> RegionVid {
|
|
|
|
|
debug!(
|
|
|
|
|
"universal_upper_bound(r={:?}={})",
|
|
|
|
|
r,
|
|
|
|
|
self.region_value_str(r)
|
|
|
|
|
);
|
|
|
|
|
debug!("universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
|
|
|
|
|
|
|
|
|
|
// Find the smallest universal region that contains all other
|
|
|
|
|
// universal regions within `region`.
|
|
|
|
@@ -956,10 +1054,7 @@ fn eval_verify_bound(
|
|
|
|
|
lower_bound: RegionVid,
|
|
|
|
|
verify_bound: &VerifyBound<'tcx>,
|
|
|
|
|
) -> bool {
|
|
|
|
|
debug!(
|
|
|
|
|
"eval_verify_bound(lower_bound={:?}, verify_bound={:?})",
|
|
|
|
|
lower_bound, verify_bound
|
|
|
|
|
);
|
|
|
|
|
debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound);
|
|
|
|
|
|
|
|
|
|
match verify_bound {
|
|
|
|
|
VerifyBound::IfEq(test_ty, verify_bound1) => {
|
|
|
|
@@ -968,7 +1063,7 @@ fn eval_verify_bound(
|
|
|
|
|
|
|
|
|
|
VerifyBound::OutlivedBy(r) => {
|
|
|
|
|
let r_vid = self.to_region_vid(r);
|
|
|
|
|
self.eval_outlives(body, r_vid, lower_bound)
|
|
|
|
|
self.eval_outlives(r_vid, lower_bound)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| {
|
|
|
|
@@ -1041,23 +1136,17 @@ fn normalize_to_scc_representatives<T>(&self, tcx: TyCtxt<'tcx>, value: T) -> T
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Evaluate whether `sup_region: sub_region @ point`.
|
|
|
|
|
fn eval_outlives(
|
|
|
|
|
&self,
|
|
|
|
|
_body: &Body<'tcx>,
|
|
|
|
|
sup_region: RegionVid,
|
|
|
|
|
sub_region: RegionVid,
|
|
|
|
|
) -> bool {
|
|
|
|
|
// Evaluate whether `sup_region == sub_region`.
|
|
|
|
|
fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool {
|
|
|
|
|
self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Evaluate whether `sup_region: sub_region`.
|
|
|
|
|
fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool {
|
|
|
|
|
debug!("eval_outlives({:?}: {:?})", sup_region, sub_region);
|
|
|
|
|
|
|
|
|
|
debug!(
|
|
|
|
|
"eval_outlives: sup_region's value = {:?}",
|
|
|
|
|
self.region_value_str(sup_region),
|
|
|
|
|
);
|
|
|
|
|
debug!(
|
|
|
|
|
"eval_outlives: sub_region's value = {:?}",
|
|
|
|
|
self.region_value_str(sub_region),
|
|
|
|
|
);
|
|
|
|
|
debug!("eval_outlives: sup_region's value = {:?}", self.region_value_str(sup_region),);
|
|
|
|
|
debug!("eval_outlives: sub_region's value = {:?}", self.region_value_str(sub_region),);
|
|
|
|
|
|
|
|
|
|
let sub_region_scc = self.constraint_sccs.scc(sub_region);
|
|
|
|
|
let sup_region_scc = self.constraint_sccs.scc(sup_region);
|
|
|
|
@@ -1068,9 +1157,8 @@ fn eval_outlives(
|
|
|
|
|
// now). Therefore, the sup-region outlives the sub-region if,
|
|
|
|
|
// for each universal region R1 in the sub-region, there
|
|
|
|
|
// exists some region R2 in the sup-region that outlives R1.
|
|
|
|
|
let universal_outlives = self.scc_values
|
|
|
|
|
.universal_regions_outlived_by(sub_region_scc)
|
|
|
|
|
.all(|r1| {
|
|
|
|
|
let universal_outlives =
|
|
|
|
|
self.scc_values.universal_regions_outlived_by(sub_region_scc).all(|r1| {
|
|
|
|
|
self.scc_values
|
|
|
|
|
.universal_regions_outlived_by(sup_region_scc)
|
|
|
|
|
.any(|r2| self.universal_region_relations.outlives(r2, r1))
|
|
|
|
@@ -1088,8 +1176,7 @@ fn eval_outlives(
|
|
|
|
|
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
|
|
|
|
@@ -1171,12 +1258,7 @@ fn check_universal_region(
|
|
|
|
|
// Because this free region must be in the ROOT universe, we
|
|
|
|
|
// know it cannot contain any bound universes.
|
|
|
|
|
assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
|
|
|
|
|
debug_assert!(
|
|
|
|
|
self.scc_values
|
|
|
|
|
.placeholders_contained_in(longer_fr_scc)
|
|
|
|
|
.next()
|
|
|
|
|
.is_none()
|
|
|
|
|
);
|
|
|
|
|
debug_assert!(self.scc_values.placeholders_contained_in(longer_fr_scc).next().is_none());
|
|
|
|
|
|
|
|
|
|
// Only check all of the relations for the main representative of each
|
|
|
|
|
// SCC, otherwise just check that we outlive said representative. This
|
|
|
|
@@ -1230,9 +1312,7 @@ fn check_universal_region_relation(
|
|
|
|
|
errors_buffer: &mut Vec<Diagnostic>,
|
|
|
|
|
) -> Option<ErrorReported> {
|
|
|
|
|
// If it is known that `fr: o`, carry on.
|
|
|
|
|
if self.universal_region_relations
|
|
|
|
|
.outlives(longer_fr, shorter_fr)
|
|
|
|
|
{
|
|
|
|
|
if self.universal_region_relations.outlives(longer_fr, shorter_fr) {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1246,9 +1326,7 @@ fn check_universal_region_relation(
|
|
|
|
|
// We'll call it `fr-` -- it's ever so slightly smaller than
|
|
|
|
|
// `longer_fr`.
|
|
|
|
|
|
|
|
|
|
if let Some(fr_minus) = self
|
|
|
|
|
.universal_region_relations
|
|
|
|
|
.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);
|
|
|
|
|
|
|
|
|
@@ -1258,12 +1336,9 @@ fn check_universal_region_relation(
|
|
|
|
|
// Grow `shorter_fr` until we find some non-local regions. (We
|
|
|
|
|
// always will.) We'll call them `shorter_fr+` -- they're ever
|
|
|
|
|
// so slightly larger than `shorter_fr`.
|
|
|
|
|
let shorter_fr_plus = self.universal_region_relations
|
|
|
|
|
.non_local_upper_bounds(&shorter_fr);
|
|
|
|
|
debug!(
|
|
|
|
|
"check_universal_region: shorter_fr_plus={:?}",
|
|
|
|
|
shorter_fr_plus
|
|
|
|
|
);
|
|
|
|
|
let shorter_fr_plus =
|
|
|
|
|
self.universal_region_relations.non_local_upper_bounds(&shorter_fr);
|
|
|
|
|
debug!("check_universal_region: shorter_fr_plus={:?}", shorter_fr_plus);
|
|
|
|
|
for &&fr in &shorter_fr_plus {
|
|
|
|
|
// Push the constraint `fr-: shorter_fr+`
|
|
|
|
|
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
|
|
|
|
@@ -1295,28 +1370,20 @@ fn check_bound_universal_region(
|
|
|
|
|
longer_fr: RegionVid,
|
|
|
|
|
placeholder: ty::PlaceholderRegion,
|
|
|
|
|
) {
|
|
|
|
|
debug!(
|
|
|
|
|
"check_bound_universal_region(fr={:?}, placeholder={:?})",
|
|
|
|
|
longer_fr, placeholder,
|
|
|
|
|
);
|
|
|
|
|
debug!("check_bound_universal_region(fr={:?}, placeholder={:?})", longer_fr, placeholder,);
|
|
|
|
|
|
|
|
|
|
let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
|
|
|
|
|
debug!(
|
|
|
|
|
"check_bound_universal_region: longer_fr_scc={:?}",
|
|
|
|
|
longer_fr_scc,
|
|
|
|
|
);
|
|
|
|
|
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
|
|
|
|
|
// else about it!
|
|
|
|
|
let error_element = match {
|
|
|
|
|
self.scc_values
|
|
|
|
|
.elements_contained_in(longer_fr_scc)
|
|
|
|
|
.find(|element| match element {
|
|
|
|
|
RegionElement::Location(_) => true,
|
|
|
|
|
RegionElement::RootUniversalRegion(_) => true,
|
|
|
|
|
RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
|
|
|
|
|
})
|
|
|
|
|
self.scc_values.elements_contained_in(longer_fr_scc).find(|element| match element {
|
|
|
|
|
RegionElement::Location(_) => true,
|
|
|
|
|
RegionElement::RootUniversalRegion(_) => true,
|
|
|
|
|
RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
|
|
|
|
|
})
|
|
|
|
|
} {
|
|
|
|
|
Some(v) => v,
|
|
|
|
|
None => return,
|
|
|
|
@@ -1327,7 +1394,8 @@ fn check_bound_universal_region(
|
|
|
|
|
let error_region = match error_element {
|
|
|
|
|
RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
|
|
|
|
|
RegionElement::RootUniversalRegion(r) => r,
|
|
|
|
|
RegionElement::PlaceholderRegion(error_placeholder) => self.definitions
|
|
|
|
|
RegionElement::PlaceholderRegion(error_placeholder) => self
|
|
|
|
|
.definitions
|
|
|
|
|
.iter_enumerated()
|
|
|
|
|
.filter_map(|(r, definition)| match definition.origin {
|
|
|
|
|
NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
|
|
|
|
@@ -1345,12 +1413,44 @@ fn check_bound_universal_region(
|
|
|
|
|
// the AST-based checker uses a more conservative check,
|
|
|
|
|
// so to even see this error, one must pass in a special
|
|
|
|
|
// flag.
|
|
|
|
|
let mut diag = infcx
|
|
|
|
|
.tcx
|
|
|
|
|
.sess
|
|
|
|
|
.struct_span_err(span, "higher-ranked subtype error");
|
|
|
|
|
let mut diag = infcx.tcx.sess.struct_span_err(span, "higher-ranked subtype error");
|
|
|
|
|
diag.emit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn check_pick_constraints(
|
|
|
|
|
&self,
|
|
|
|
|
infcx: &InferCtxt<'_, 'tcx>,
|
|
|
|
|
mir_def_id: DefId,
|
|
|
|
|
errors_buffer: &mut Vec<Diagnostic>, // TODO
|
|
|
|
|
) {
|
|
|
|
|
let pick_constraints = self.pick_constraints.clone();
|
|
|
|
|
for p_c_i in pick_constraints.all_indices() {
|
|
|
|
|
debug!("check_pick_constraint(p_c_i={:?})", p_c_i);
|
|
|
|
|
let p_c = &pick_constraints[p_c_i];
|
|
|
|
|
let pick_region_vid = p_c.pick_region_vid;
|
|
|
|
|
debug!("check_pick_constraint: pick_region_vid={:?} with value {}", pick_region_vid, self.region_value_str(pick_region_vid));
|
|
|
|
|
let option_regions = pick_constraints.option_regions(p_c_i);
|
|
|
|
|
debug!("check_pick_constraint: option_regions={:?}", option_regions);
|
|
|
|
|
|
|
|
|
|
// did the pick-region wind up equal to any of the option regions?
|
|
|
|
|
if let Some(o) = option_regions.iter().find(|&&o_r| self.eval_equal(o_r, p_c.pick_region_vid)) {
|
|
|
|
|
debug!("check_pick_constraint: evaluated as equal to {:?}", o);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if not, report an error
|
|
|
|
|
let region_scope_tree = &infcx.tcx.region_scope_tree(mir_def_id);
|
|
|
|
|
let pick_region = infcx.tcx.mk_region(ty::ReVar(pick_region_vid)); // XXX
|
|
|
|
|
opaque_types::unexpected_hidden_region_diagnostic(
|
|
|
|
|
infcx.tcx,
|
|
|
|
|
Some(region_scope_tree),
|
|
|
|
|
p_c.opaque_type_def_id,
|
|
|
|
|
p_c.hidden_ty,
|
|
|
|
|
pick_region,
|
|
|
|
|
)
|
|
|
|
|
.buffer(errors_buffer);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> RegionDefinition<'tcx> {
|
|
|
|
@@ -1364,11 +1464,7 @@ fn new(universe: ty::UniverseIndex, rv_origin: RegionVariableOrigin) -> Self {
|
|
|
|
|
_ => NLLRegionVariableOrigin::Existential,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Self {
|
|
|
|
|
origin,
|
|
|
|
|
universe,
|
|
|
|
|
external_name: None,
|
|
|
|
|
}
|
|
|
|
|
Self { origin, universe, external_name: None }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1471,10 +1567,7 @@ fn subst_closure_mapping<T>(
|
|
|
|
|
if let ty::ReClosureBound(vid) = r {
|
|
|
|
|
closure_mapping[*vid]
|
|
|
|
|
} else {
|
|
|
|
|
bug!(
|
|
|
|
|
"subst_closure_mapping: encountered non-closure bound free region {:?}",
|
|
|
|
|
r
|
|
|
|
|
)
|
|
|
|
|
bug!("subst_closure_mapping: encountered non-closure bound free region {:?}", r)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|