1
Fork 0

track if any region constraints involved placeholders

This commit is contained in:
Niko Matsakis 2018-11-20 10:24:38 -05:00
parent 13ea9b877c
commit 2c17af0bf7
3 changed files with 33 additions and 14 deletions

View file

@ -867,10 +867,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
r r
} }
/// Scan the constraints produced since `snapshot` began and returns:
///
/// - None -- if none of them involve "region outlives" constraints
/// - Some(true) -- if there are `'a: 'b` constraints where `'a` or `'b` is a placehodler
/// - Some(false) -- if there are `'a: 'b` constraints but none involve placeholders
pub fn region_constraints_added_in_snapshot( pub fn region_constraints_added_in_snapshot(
&self, &self,
snapshot: &CombinedSnapshot<'a, 'tcx>, snapshot: &CombinedSnapshot<'a, 'tcx>,
) -> bool { ) -> Option<bool> {
self.borrow_region_constraints().region_constraints_added_in_snapshot( self.borrow_region_constraints().region_constraints_added_in_snapshot(
&snapshot.region_constraints_snapshot, &snapshot.region_constraints_snapshot,
) )

View file

@ -128,6 +128,16 @@ pub enum Constraint<'tcx> {
RegSubReg(Region<'tcx>, Region<'tcx>), RegSubReg(Region<'tcx>, Region<'tcx>),
} }
impl Constraint<'_> {
pub fn involves_placeholders(&self) -> bool {
match self {
Constraint::VarSubVar(_, _) => false,
Constraint::VarSubReg(_, r) | Constraint::RegSubVar(r, _) => r.is_placeholder(),
Constraint::RegSubReg(r, s) => r.is_placeholder() || s.is_placeholder(),
}
}
}
/// VerifyGenericBound(T, _, R, RS): The parameter type `T` (or /// VerifyGenericBound(T, _, R, RS): The parameter type `T` (or
/// associated type) must outlive the region `R`. `T` is known to /// associated type) must outlive the region `R`. `T` is known to
/// outlive `RS`. Therefore verify that `R <= RS[i]` for some /// outlive `RS`. Therefore verify that `R <= RS[i]` for some
@ -324,6 +334,8 @@ impl TaintDirections {
} }
} }
pub struct ConstraintInfo {}
impl<'tcx> RegionConstraintCollector<'tcx> { impl<'tcx> RegionConstraintCollector<'tcx> {
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
@ -485,7 +497,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
) -> RegionVid { ) -> RegionVid {
let vid = self.var_infos.push(RegionVariableInfo { origin, universe }); let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
let u_vid = self.unification_table let u_vid = self
.unification_table
.new_key(unify_key::RegionVidKey { min_vid: vid }); .new_key(unify_key::RegionVidKey { min_vid: vid });
assert_eq!(vid, u_vid); assert_eq!(vid, u_vid);
if self.in_snapshot() { if self.in_snapshot() {
@ -517,7 +530,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
assert!(self.in_snapshot()); assert!(self.in_snapshot());
let constraints_to_kill: Vec<usize> = self.undo_log let constraints_to_kill: Vec<usize> = self
.undo_log
.iter() .iter()
.enumerate() .enumerate()
.rev() .rev()
@ -820,17 +834,18 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
.filter_map(|&elt| match elt { .filter_map(|&elt| match elt {
AddVar(vid) => Some(vid), AddVar(vid) => Some(vid),
_ => None, _ => None,
}) }).collect()
.collect()
} }
pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> bool { /// See [`RegionInference::region_constraints_added_in_snapshot`]
pub fn region_constraints_added_in_snapshot(&self, mark: &RegionSnapshot) -> Option<bool> {
self.undo_log[mark.length..] self.undo_log[mark.length..]
.iter() .iter()
.any(|&elt| match elt { .map(|&elt| match elt {
AddConstraint(_) => true, AddConstraint(constraint) => Some(constraint.involves_placeholders()),
_ => false, _ => None,
}) }).max()
.unwrap_or(None)
} }
} }

View file

@ -639,10 +639,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
) -> Result<EvaluationResult, OverflowError> { ) -> Result<EvaluationResult, OverflowError> {
self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> { self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {
let result = op(self)?; let result = op(self)?;
if !self.infcx.region_constraints_added_in_snapshot(snapshot) { match self.infcx.region_constraints_added_in_snapshot(snapshot) {
Ok(result) None => Ok(result),
} else { Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),
Ok(result.max(EvaluatedToOkModuloRegions))
} }
}) })
} }