1
Fork 0

apply process_registered_region_obligations at the end of regionck

We used to apply it repeatedly as we went, relying on the current
value of the `region_bound_pairs_accum` vector. But now we save those
values into a map, so we can just process all the registered region
obligations at the end.
This commit is contained in:
Niko Matsakis 2018-09-12 17:48:51 -04:00
parent 9e305a8a23
commit b2e0215a1f
9 changed files with 52 additions and 64 deletions

View file

@ -97,8 +97,8 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a> OutlivesEnvironment<'tcx> {
}
/// Borrows current value of the `region_bound_pairs`.
pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
&self.region_bound_pairs_accum
pub fn region_bound_pairs_map(&self) -> &FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>> {
&self.region_bound_pairs_map
}
/// Returns ownership of the `free_region_map`.

View file

@ -70,8 +70,9 @@
//! imply that `'b: 'a`.
use hir::def_id::DefId;
use infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
use infer::outlives::env::RegionBoundPairs;
use infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
use rustc_data_structures::fx::FxHashMap;
use syntax::ast;
use traits::{self, ObligationCause};
use ty::outlives::Component;
@ -159,10 +160,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// processed.
pub fn process_registered_region_obligations(
&self,
region_bound_pairs: &RegionBoundPairs<'tcx>,
region_bound_pairs_map: &FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>>,
implicit_region_bound: Option<ty::Region<'tcx>>,
param_env: ty::ParamEnv<'tcx>,
body_id: ast::NodeId,
) {
assert!(
!self.in_snapshot.get(),
@ -171,28 +171,16 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
debug!("process_registered_region_obligations()");
// pull out the region obligations with the given `body_id` (leaving the rest)
let mut my_region_obligations = Vec::with_capacity(self.region_obligations.borrow().len());
{
let mut r_o = self.region_obligations.borrow_mut();
my_region_obligations.extend(r_o.drain_filter(|(ro_body_id, _)| {
*ro_body_id == body_id
}).map(|(_, obligation)| obligation));
}
let my_region_obligations = self.take_registered_region_obligations();
let outlives = &mut TypeOutlives::new(
self,
self.tcx,
region_bound_pairs,
implicit_region_bound,
param_env,
);
for RegionObligation {
for (
body_id,
RegionObligation {
sup_type,
sub_region,
origin,
} in my_region_obligations
},
) in my_region_obligations
{
debug!(
"process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}",
@ -200,7 +188,22 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
);
let sup_type = self.resolve_type_vars_if_possible(&sup_type);
if let Some(region_bound_pairs) = region_bound_pairs_map.get(&body_id) {
let outlives = &mut TypeOutlives::new(
self,
self.tcx,
&region_bound_pairs,
implicit_region_bound,
param_env,
);
outlives.type_must_outlive(origin, sup_type, sub_region);
} else {
self.tcx.sess.delay_span_bug(
origin.span(),
&format!("no region-bound-pairs for {:?}", body_id),
)
}
}
}

View file

@ -16,10 +16,9 @@ use super::*;
use std::collections::hash_map::Entry;
use std::collections::VecDeque;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use infer::region_constraints::{Constraint, RegionConstraintData};
use infer::InferCtxt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use ty::fold::TypeFolder;
use ty::{Region, RegionVid};
@ -231,16 +230,14 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
})
.collect();
let body_ids: FxHashSet<_> = infcx
let body_id_map: FxHashMap<_, _> = infcx
.region_obligations
.borrow()
.iter()
.map(|&(id, _)| id)
.map(|&(id, _)| (id, vec![]))
.collect();
for id in body_ids {
infcx.process_registered_region_obligations(&vec![], None, full_env.clone(), id);
}
infcx.process_registered_region_obligations(&body_id_map, None, full_env.clone());
let region_data = infcx
.borrow_region_constraints()

View file

@ -88,7 +88,7 @@ use middle::mem_categorization as mc;
use middle::mem_categorization::Categorization;
use middle::region;
use rustc::hir::def_id::DefId;
use rustc::infer::{self, UnlessNll};
use rustc::infer::{self, RegionObligation, UnlessNll};
use rustc::infer::outlives::env::OutlivesEnvironment;
use rustc::ty::adjustment;
use rustc::ty::subst::Substs;
@ -390,16 +390,15 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
// which, when processed, might generate new region
// obligations. So make sure we process those.
self.select_all_obligations_or_error();
self.infcx.process_registered_region_obligations(
self.outlives_environment.region_bound_pairs(),
self.implicit_region_bound,
self.param_env,
self.body_id,
);
}
fn resolve_regions_and_report_errors(&self, unless_nll: UnlessNll) {
self.infcx.process_registered_region_obligations(
self.outlives_environment.region_bound_pairs_map(),
self.implicit_region_bound,
self.param_env,
);
self.fcx.resolve_regions_and_report_errors(
self.subject_def_id,
&self.region_scope_tree,
@ -1042,13 +1041,13 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
ty: Ty<'tcx>,
region: ty::Region<'tcx>,
) {
self.infcx.type_must_outlive(
self.outlives_environment.region_bound_pairs(),
self.implicit_region_bound,
self.param_env,
self.infcx.register_region_obligation(
self.body_id,
RegionObligation {
sub_region: region,
sup_type: ty,
origin,
ty,
region,
},
);
}

View file

@ -1,11 +0,0 @@
error[E0621]: explicit lifetime required in the type of `value`
--> $DIR/issue-16922.rs:14:5
|
LL | fn foo<T: Any>(value: &T) -> Box<Any> {
| -- help: add explicit lifetime `'static` to the type of `value`: `&'static T`
LL | Box::new(value) as Box<Any>
| ^^^^^^^^^^^^^^^ lifetime `'static` required
error: aborting due to previous error
For more information about this error, try `rustc --explain E0621`.

View file

@ -4,7 +4,7 @@ error[E0621]: explicit lifetime required in the type of `value`
LL | fn foo<T: Any>(value: &T) -> Box<Any> {
| -- help: add explicit lifetime `'static` to the type of `value`: `&'static T`
LL | Box::new(value) as Box<Any>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
| ^^^^^^^^^^^^^^^ lifetime `'static` required
error: aborting due to previous error

View file

@ -9,7 +9,7 @@ note: first, the lifetime cannot outlive the lifetime 'a as defined on the funct
|
LL | fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
| ^^
note: ...so that the type `(dyn SomeTrait + 'a)` is not borrowed for too long
note: ...so that reference does not outlive borrowed content
--> $DIR/object-lifetime-default-elision.rs:81:5
|
LL | ss

View file

@ -9,7 +9,7 @@ note: first, the lifetime cannot outlive the lifetime 'a as defined on the funct
|
LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a Foo) -> &'b () {
| ^^
note: ...so that the type `(dyn Foo + 'a)` is not borrowed for too long
note: ...so that reference does not outlive borrowed content
--> $DIR/region-object-lifetime-2.rs:20:5
|
LL | x.borrowed() //~ ERROR cannot infer

View file

@ -26,7 +26,7 @@ note: first, the lifetime cannot outlive the lifetime 'a as defined on the funct
|
LL | fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
| ^^
note: ...so that the type `(dyn Dummy + 'a)` is not borrowed for too long
note: ...so that reference does not outlive borrowed content
--> $DIR/regions-trait-object-subtyping.rs:25:5
|
LL | x //~ ERROR lifetime bound not satisfied