replace LexicalRegionConstraintData with QueryRegionConstraint
This commit is contained in:
parent
2624c14a26
commit
c8cf710ce0
6 changed files with 84 additions and 121 deletions
|
|
@ -44,7 +44,7 @@ use rustc_data_structures::indexed_vec::IndexVec;
|
|||
|
||||
mod canonicalizer;
|
||||
|
||||
mod query_result;
|
||||
pub mod query_result;
|
||||
|
||||
mod substitute;
|
||||
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
|
||||
/// Given the region obligations and constraints scraped from the infcx,
|
||||
/// creates query region constraints.
|
||||
fn make_query_outlives<'tcx>(
|
||||
pub fn make_query_outlives<'tcx>(
|
||||
tcx: TyCtxt<'_, '_, 'tcx>,
|
||||
region_obligations: Vec<(ast::NodeId, RegionObligation<'tcx>)>,
|
||||
region_constraints: &RegionConstraintData<'tcx>,
|
||||
|
|
|
|||
|
|
@ -11,13 +11,15 @@
|
|||
use borrow_check::location::LocationTable;
|
||||
use borrow_check::nll::facts::AllFacts;
|
||||
use borrow_check::nll::region_infer::{OutlivesConstraint, RegionTest, TypeTest};
|
||||
use borrow_check::nll::type_check::{Locations, LexicalRegionConstraintData};
|
||||
use borrow_check::nll::type_check::Locations;
|
||||
use borrow_check::nll::universal_regions::UniversalRegions;
|
||||
use rustc::infer::{self, RegionObligation, SubregionOrigin};
|
||||
use rustc::infer::canonical::QueryRegionConstraint;
|
||||
use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
|
||||
use rustc::infer::region_constraints::{Constraint, GenericKind, VerifyBound};
|
||||
use rustc::infer::region_constraints::{GenericKind, VerifyBound};
|
||||
use rustc::infer::{self, SubregionOrigin};
|
||||
use rustc::mir::{Location, Mir};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::subst::UnpackedKind;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
|
||||
|
|
@ -63,49 +65,10 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn convert(&mut self, data: &LexicalRegionConstraintData<'tcx>) {
|
||||
pub(super) fn convert(&mut self, query_constraints: &[QueryRegionConstraint<'tcx>]) {
|
||||
debug!("generate: constraints at: {:#?}", self.locations);
|
||||
let LexicalRegionConstraintData {
|
||||
constraints,
|
||||
region_obligations,
|
||||
} = data;
|
||||
|
||||
for constraint in constraints {
|
||||
debug!("generate: constraint: {:?}", constraint);
|
||||
let (a_vid, b_vid) = match constraint {
|
||||
Constraint::VarSubVar(a_vid, b_vid) => (*a_vid, *b_vid),
|
||||
Constraint::RegSubVar(a_r, b_vid) => (self.to_region_vid(a_r), *b_vid),
|
||||
Constraint::VarSubReg(a_vid, b_r) => (*a_vid, self.to_region_vid(b_r)),
|
||||
Constraint::RegSubReg(a_r, b_r) => {
|
||||
(self.to_region_vid(a_r), self.to_region_vid(b_r))
|
||||
}
|
||||
};
|
||||
|
||||
// We have the constraint that `a_vid <= b_vid`. Add
|
||||
// `b_vid: a_vid` to our region checker. Note that we
|
||||
// reverse direction, because `regioncx` talks about
|
||||
// "outlives" (`>=`) whereas the region constraints
|
||||
// talk about `<=`.
|
||||
self.add_outlives(b_vid, a_vid);
|
||||
|
||||
// In the new analysis, all outlives relations etc
|
||||
// "take effect" at the mid point of the statement
|
||||
// that requires them, so ignore the `at_location`.
|
||||
if let Some(all_facts) = &mut self.all_facts {
|
||||
if let Some(from_location) = self.locations.from_location() {
|
||||
all_facts.outlives.push((
|
||||
b_vid,
|
||||
a_vid,
|
||||
self.location_table.mid_index(from_location),
|
||||
));
|
||||
} else {
|
||||
for location in self.location_table.all_points() {
|
||||
all_facts.outlives.push((b_vid, a_vid, location));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract out various useful fields we'll need below.
|
||||
let ConstraintConversion {
|
||||
tcx,
|
||||
region_bound_pairs,
|
||||
|
|
@ -113,23 +76,59 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
|
|||
param_env,
|
||||
..
|
||||
} = *self;
|
||||
for r_o in region_obligations {
|
||||
let RegionObligation {
|
||||
sup_type,
|
||||
sub_region,
|
||||
cause,
|
||||
} = r_o;
|
||||
|
||||
// we don't actually use this for anything.
|
||||
let origin = infer::RelateParamBound(cause.span, sup_type);
|
||||
for query_constraint in query_constraints {
|
||||
// At the moment, we never generate any "higher-ranked"
|
||||
// region constraints like `for<'a> 'a: 'b`. At some point
|
||||
// when we move to universes, we will, and this assertion
|
||||
// will start to fail.
|
||||
let ty::OutlivesPredicate(k1, r2) =
|
||||
query_constraint.no_late_bound_regions().unwrap_or_else(|| {
|
||||
span_bug!(
|
||||
self.span(),
|
||||
"query_constraint {:?} contained bound regions",
|
||||
query_constraint,
|
||||
);
|
||||
});
|
||||
|
||||
TypeOutlives::new(
|
||||
&mut *self,
|
||||
tcx,
|
||||
region_bound_pairs,
|
||||
implicit_region_bound,
|
||||
param_env,
|
||||
).type_must_outlive(origin, sup_type, sub_region);
|
||||
match k1.unpack() {
|
||||
UnpackedKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
let r2_vid = self.to_region_vid(r2);
|
||||
self.add_outlives(r1_vid, r2_vid);
|
||||
|
||||
// In the new analysis, all outlives relations etc
|
||||
// "take effect" at the mid point of the statement
|
||||
// that requires them, so ignore the `at_location`.
|
||||
if let Some(all_facts) = &mut self.all_facts {
|
||||
if let Some(from_location) = self.locations.from_location() {
|
||||
all_facts.outlives.push((
|
||||
r1_vid,
|
||||
r2_vid,
|
||||
self.location_table.mid_index(from_location),
|
||||
));
|
||||
} else {
|
||||
for location in self.location_table.all_points() {
|
||||
all_facts.outlives.push((r1_vid, r2_vid, location));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnpackedKind::Type(t1) => {
|
||||
// we don't actually use this for anything, but
|
||||
// the `TypeOutlives` code needs an origin.
|
||||
let origin = infer::RelateParamBound(self.span(), t1);
|
||||
|
||||
TypeOutlives::new(
|
||||
&mut *self,
|
||||
tcx,
|
||||
region_bound_pairs,
|
||||
implicit_region_bound,
|
||||
param_env,
|
||||
).type_must_outlive(origin, t1, r2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -185,17 +184,12 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn span(&self) -> Span {
|
||||
self
|
||||
.mir
|
||||
self.mir
|
||||
.source_info(self.locations.from_location().unwrap_or(Location::START))
|
||||
.span
|
||||
}
|
||||
|
||||
fn add_outlives(
|
||||
&mut self,
|
||||
sup: ty::RegionVid,
|
||||
sub: ty::RegionVid,
|
||||
) {
|
||||
fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
|
||||
let span = self.span();
|
||||
let point = self.locations.at_location().unwrap_or(Location::START);
|
||||
|
||||
|
|
@ -213,7 +207,9 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'gcx, 'tcx> {
|
||||
impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx>
|
||||
for &'a mut ConstraintConversion<'b, 'gcx, 'tcx>
|
||||
{
|
||||
fn push_sub_region_constraint(
|
||||
&mut self,
|
||||
_origin: SubregionOrigin<'tcx>,
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@
|
|||
|
||||
use borrow_check::nll::region_infer::Cause;
|
||||
use borrow_check::nll::type_check::type_op::{DropckOutlives, TypeOp};
|
||||
use borrow_check::nll::type_check::{AtLocation, LexicalRegionConstraintData};
|
||||
use borrow_check::nll::type_check::AtLocation;
|
||||
use dataflow::move_paths::{HasMoveData, MoveData};
|
||||
use dataflow::MaybeInitializedPlaces;
|
||||
use dataflow::{FlowAtLocation, FlowsAtLocation};
|
||||
use rustc::infer::canonical::QueryRegionConstraint;
|
||||
use rustc::mir::Local;
|
||||
use rustc::mir::{BasicBlock, Location, Mir};
|
||||
use rustc::ty::subst::Kind;
|
||||
|
|
@ -70,7 +71,7 @@ where
|
|||
|
||||
struct DropData<'tcx> {
|
||||
dropped_kinds: Vec<Kind<'tcx>>,
|
||||
region_constraint_data: Option<Rc<LexicalRegionConstraintData<'tcx>>>,
|
||||
region_constraint_data: Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>,
|
||||
}
|
||||
|
||||
impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flow, 'gcx, 'tcx> {
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ use dataflow::move_paths::MoveData;
|
|||
use dataflow::FlowAtLocation;
|
||||
use dataflow::MaybeInitializedPlaces;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer::region_constraints::{Constraint, GenericKind};
|
||||
use rustc::infer::{InferCtxt, LateBoundRegionConversionTime, RegionObligation, UnitResult};
|
||||
use rustc::infer::canonical::QueryRegionConstraint;
|
||||
use rustc::infer::region_constraints::GenericKind;
|
||||
use rustc::infer::{InferCtxt, LateBoundRegionConversionTime, UnitResult};
|
||||
use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
|
||||
use rustc::mir::tcx::PlaceTy;
|
||||
use rustc::mir::visit::{PlaceContext, Visitor};
|
||||
|
|
@ -625,21 +626,6 @@ crate struct MirTypeckRegionConstraints<'tcx> {
|
|||
crate type_tests: Vec<TypeTest<'tcx>>,
|
||||
}
|
||||
|
||||
/// The type checker layers on top of the "old" inference engine. The
|
||||
/// idea is that we run some operations, like trait selection, and
|
||||
/// then we "scrape out" the region constraints that have accumulated
|
||||
/// from the old lexical solver. This struct just collects the bits of
|
||||
/// that data that we care about into one place.
|
||||
#[derive(Debug)]
|
||||
struct LexicalRegionConstraintData<'tcx> {
|
||||
/// The `'a <= 'b` constraints extracted from `RegionConstraintData`.
|
||||
constraints: Vec<Constraint<'tcx>>,
|
||||
|
||||
/// The `T: 'a` (and `'a: 'b`, in some cases) constraints
|
||||
/// extracted from the pending "region obligations".
|
||||
region_obligations: Vec<RegionObligation<'tcx>>,
|
||||
}
|
||||
|
||||
/// The `Locations` type summarizes *where* region constraints are
|
||||
/// required to hold. Normally, this is at a particular point which
|
||||
/// created the obligation, but for constraints that the user gave, we
|
||||
|
|
@ -759,7 +745,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||
fn push_region_constraints(
|
||||
&mut self,
|
||||
locations: Locations,
|
||||
data: &LexicalRegionConstraintData<'tcx>,
|
||||
data: &[QueryRegionConstraint<'tcx>],
|
||||
) {
|
||||
debug!(
|
||||
"push_region_constraints: constraints generated at {:?} are {:#?}",
|
||||
|
|
@ -1703,10 +1689,3 @@ impl ToLocations for Location {
|
|||
self.at_self()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> LexicalRegionConstraintData<'tcx> {
|
||||
fn is_empty(&self) -> bool {
|
||||
let LexicalRegionConstraintData { constraints, region_obligations } = self;
|
||||
constraints.is_empty() && region_obligations.is_empty()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use borrow_check::nll::type_check::LexicalRegionConstraintData;
|
||||
use rustc::infer::region_constraints::RegionConstraintData;
|
||||
use rustc::infer::canonical::query_result;
|
||||
use rustc::infer::canonical::QueryRegionConstraint;
|
||||
use rustc::infer::{InferCtxt, InferOk, InferResult};
|
||||
use rustc::traits::query::NoSolution;
|
||||
use rustc::traits::{Normalized, Obligation, ObligationCause, PredicateObligation, TraitEngine};
|
||||
|
|
@ -44,7 +44,7 @@ pub(super) trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
|
|||
fn fully_perform(
|
||||
self,
|
||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||
) -> Result<(Self::Output, Option<Rc<LexicalRegionConstraintData<'tcx>>>), TypeError<'tcx>> {
|
||||
) -> Result<(Self::Output, Option<Rc<Vec<QueryRegionConstraint<'tcx>>>>), TypeError<'tcx>> {
|
||||
let op = match self.trivial_noop() {
|
||||
Ok(r) => return Ok((r, None)),
|
||||
Err(op) => op,
|
||||
|
|
@ -66,33 +66,20 @@ pub(super) trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
|
|||
);
|
||||
}
|
||||
|
||||
let region_obligations: Vec<_> = infcx
|
||||
.take_registered_region_obligations()
|
||||
.into_iter()
|
||||
.map(|(_node_id, region_obligation)| region_obligation)
|
||||
.collect();
|
||||
let region_obligations = infcx.take_registered_region_obligations();
|
||||
|
||||
let RegionConstraintData {
|
||||
constraints,
|
||||
verifys,
|
||||
givens,
|
||||
} = infcx.take_and_reset_region_constraints();
|
||||
let region_constraint_data = infcx.take_and_reset_region_constraints();
|
||||
|
||||
// These are created when we "process" the registered region
|
||||
// obliations, and that hasn't happened yet.
|
||||
assert!(verifys.is_empty());
|
||||
|
||||
// NLL doesn't use givens (and thank goodness!).
|
||||
assert!(givens.is_empty());
|
||||
|
||||
let data = LexicalRegionConstraintData {
|
||||
constraints: constraints.keys().cloned().collect(),
|
||||
let outlives = query_result::make_query_outlives(
|
||||
infcx.tcx,
|
||||
region_obligations,
|
||||
};
|
||||
if data.is_empty() {
|
||||
®ion_constraint_data,
|
||||
);
|
||||
|
||||
if outlives.is_empty() {
|
||||
Ok((value, None))
|
||||
} else {
|
||||
Ok((value, Some(Rc::new(data))))
|
||||
Ok((value, Some(Rc::new(outlives))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue