From b2e0215a1f38e38f260f9295aca98e99f6f6a400 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 12 Sep 2018 17:48:51 -0400 Subject: [PATCH] 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. --- src/librustc/infer/outlives/env.rs | 4 +- src/librustc/infer/outlives/obligations.rs | 53 ++++++++++--------- src/librustc/traits/auto_trait.rs | 11 ++-- src/librustc_typeck/check/regionck.rs | 29 +++++----- src/test/ui/issues/issue-16922.nll.stderr | 11 ---- src/test/ui/issues/issue-16922.stderr | 2 +- .../object-lifetime-default-elision.stderr | 2 +- .../regions/region-object-lifetime-2.stderr | 2 +- .../regions-trait-object-subtyping.stderr | 2 +- 9 files changed, 52 insertions(+), 64 deletions(-) delete mode 100644 src/test/ui/issues/issue-16922.nll.stderr diff --git a/src/librustc/infer/outlives/env.rs b/src/librustc/infer/outlives/env.rs index 8deabacab5c..631ff58d3e3 100644 --- a/src/librustc/infer/outlives/env.rs +++ b/src/librustc/infer/outlives/env.rs @@ -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> { + &self.region_bound_pairs_map } /// Returns ownership of the `free_region_map`. diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index e1f7dcfd90a..899699d1113 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -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>, implicit_region_bound: Option>, 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 { - sup_type, - sub_region, - origin, - } in my_region_obligations + for ( + body_id, + RegionObligation { + sup_type, + sub_region, + origin, + }, + ) 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); - 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, + ®ion_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), + ) + } } } diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index e177382430b..8f106a08125 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -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() diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 3c462c1ae7a..bc3525adad5 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -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, - origin, - ty, - region, + self.infcx.register_region_obligation( + self.body_id, + RegionObligation { + sub_region: region, + sup_type: ty, + origin, + }, ); } diff --git a/src/test/ui/issues/issue-16922.nll.stderr b/src/test/ui/issues/issue-16922.nll.stderr deleted file mode 100644 index 3406d534896..00000000000 --- a/src/test/ui/issues/issue-16922.nll.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0621]: explicit lifetime required in the type of `value` - --> $DIR/issue-16922.rs:14:5 - | -LL | fn foo(value: &T) -> Box { - | -- help: add explicit lifetime `'static` to the type of `value`: `&'static T` -LL | Box::new(value) as Box - | ^^^^^^^^^^^^^^^ lifetime `'static` required - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0621`. diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr index e70869eb183..3406d534896 100644 --- a/src/test/ui/issues/issue-16922.stderr +++ b/src/test/ui/issues/issue-16922.stderr @@ -4,7 +4,7 @@ error[E0621]: explicit lifetime required in the type of `value` LL | fn foo(value: &T) -> Box { | -- help: add explicit lifetime `'static` to the type of `value`: `&'static T` LL | Box::new(value) as Box - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required + | ^^^^^^^^^^^^^^^ lifetime `'static` required error: aborting due to previous error diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr index 45e7d8451f7..b8c22583ff8 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -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 diff --git a/src/test/ui/regions/region-object-lifetime-2.stderr b/src/test/ui/regions/region-object-lifetime-2.stderr index e396680f99b..314f43585fe 100644 --- a/src/test/ui/regions/region-object-lifetime-2.stderr +++ b/src/test/ui/regions/region-object-lifetime-2.stderr @@ -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 diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr index 1b078855efd..a281b36946b 100644 --- a/src/test/ui/regions/regions-trait-object-subtyping.stderr +++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr @@ -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