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`. /// Borrows current value of the `region_bound_pairs`.
pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> { pub fn region_bound_pairs_map(&self) -> &FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>> {
&self.region_bound_pairs_accum &self.region_bound_pairs_map
} }
/// Returns ownership of the `free_region_map`. /// Returns ownership of the `free_region_map`.

View file

@ -70,8 +70,9 @@
//! imply that `'b: 'a`. //! imply that `'b: 'a`.
use hir::def_id::DefId; use hir::def_id::DefId;
use infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
use infer::outlives::env::RegionBoundPairs; use infer::outlives::env::RegionBoundPairs;
use infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound};
use rustc_data_structures::fx::FxHashMap;
use syntax::ast; use syntax::ast;
use traits::{self, ObligationCause}; use traits::{self, ObligationCause};
use ty::outlives::Component; use ty::outlives::Component;
@ -159,10 +160,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
/// processed. /// processed.
pub fn process_registered_region_obligations( pub fn process_registered_region_obligations(
&self, &self,
region_bound_pairs: &RegionBoundPairs<'tcx>, region_bound_pairs_map: &FxHashMap<ast::NodeId, RegionBoundPairs<'tcx>>,
implicit_region_bound: Option<ty::Region<'tcx>>, implicit_region_bound: Option<ty::Region<'tcx>>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body_id: ast::NodeId,
) { ) {
assert!( assert!(
!self.in_snapshot.get(), !self.in_snapshot.get(),
@ -171,28 +171,16 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
debug!("process_registered_region_obligations()"); debug!("process_registered_region_obligations()");
// pull out the region obligations with the given `body_id` (leaving the rest) let my_region_obligations = self.take_registered_region_obligations();
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 outlives = &mut TypeOutlives::new( for (
self, body_id,
self.tcx, RegionObligation {
region_bound_pairs, sup_type,
implicit_region_bound, sub_region,
param_env, origin,
); },
) in my_region_obligations
for RegionObligation {
sup_type,
sub_region,
origin,
} in my_region_obligations
{ {
debug!( debug!(
"process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}", "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); let sup_type = self.resolve_type_vars_if_possible(&sup_type);
outlives.type_must_outlive(origin, sup_type, sub_region);
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::hash_map::Entry;
use std::collections::VecDeque; use std::collections::VecDeque;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use infer::region_constraints::{Constraint, RegionConstraintData}; use infer::region_constraints::{Constraint, RegionConstraintData};
use infer::InferCtxt; use infer::InferCtxt;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use ty::fold::TypeFolder; use ty::fold::TypeFolder;
use ty::{Region, RegionVid}; use ty::{Region, RegionVid};
@ -231,16 +230,14 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
}) })
.collect(); .collect();
let body_ids: FxHashSet<_> = infcx let body_id_map: FxHashMap<_, _> = infcx
.region_obligations .region_obligations
.borrow() .borrow()
.iter() .iter()
.map(|&(id, _)| id) .map(|&(id, _)| (id, vec![]))
.collect(); .collect();
for id in body_ids { infcx.process_registered_region_obligations(&body_id_map, None, full_env.clone());
infcx.process_registered_region_obligations(&vec![], None, full_env.clone(), id);
}
let region_data = infcx let region_data = infcx
.borrow_region_constraints() .borrow_region_constraints()

View file

@ -88,7 +88,7 @@ use middle::mem_categorization as mc;
use middle::mem_categorization::Categorization; use middle::mem_categorization::Categorization;
use middle::region; use middle::region;
use rustc::hir::def_id::DefId; 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::infer::outlives::env::OutlivesEnvironment;
use rustc::ty::adjustment; use rustc::ty::adjustment;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
@ -390,16 +390,15 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
// which, when processed, might generate new region // which, when processed, might generate new region
// obligations. So make sure we process those. // obligations. So make sure we process those.
self.select_all_obligations_or_error(); 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) { 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.fcx.resolve_regions_and_report_errors(
self.subject_def_id, self.subject_def_id,
&self.region_scope_tree, &self.region_scope_tree,
@ -1042,13 +1041,13 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
ty: Ty<'tcx>, ty: Ty<'tcx>,
region: ty::Region<'tcx>, region: ty::Region<'tcx>,
) { ) {
self.infcx.type_must_outlive( self.infcx.register_region_obligation(
self.outlives_environment.region_bound_pairs(), self.body_id,
self.implicit_region_bound, RegionObligation {
self.param_env, sub_region: region,
origin, sup_type: ty,
ty, origin,
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> { LL | fn foo<T: Any>(value: &T) -> Box<Any> {
| -- help: add explicit lifetime `'static` to the type of `value`: `&'static T` | -- help: add explicit lifetime `'static` to the type of `value`: `&'static T`
LL | Box::new(value) as Box<Any> LL | Box::new(value) as Box<Any>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required | ^^^^^^^^^^^^^^^ lifetime `'static` required
error: aborting due to previous error 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 { 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 --> $DIR/object-lifetime-default-elision.rs:81:5
| |
LL | ss 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 () { 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 --> $DIR/region-object-lifetime-2.rs:20:5
| |
LL | x.borrowed() //~ ERROR cannot infer 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 { 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 --> $DIR/regions-trait-object-subtyping.rs:25:5
| |
LL | x //~ ERROR lifetime bound not satisfied LL | x //~ ERROR lifetime bound not satisfied