diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2017-11-04 05:37:18 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2017-11-15 16:49:22 -0500 |
| commit | 3cc44a569ded1484b0ab4fcc5b8cfd545ea3a4b5 (patch) | |
| tree | 70f90a92270f5976af4e7445ae399cd18e294dad /src | |
| parent | e0630e868320bc298da6f93ae06c8b32a829d01b (diff) | |
| download | rust-3cc44a569ded1484b0ab4fcc5b8cfd545ea3a4b5.tar.gz rust-3cc44a569ded1484b0ab4fcc5b8cfd545ea3a4b5.zip | |
do not invoke `required_region_bounds` in `region_obligations`
Instead, just search the param env predicates directly. This is equivalent to what we were doing before but more efficient.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/infer/region_obligations.rs | 40 | ||||
| -rw-r--r-- | src/librustc/ty/mod.rs | 6 |
2 files changed, 40 insertions, 6 deletions
diff --git a/src/librustc/infer/region_obligations.rs b/src/librustc/infer/region_obligations.rs index 4cd9c3f9ae3..05e14daa281 100644 --- a/src/librustc/infer/region_obligations.rs +++ b/src/librustc/infer/region_obligations.rs @@ -470,9 +470,16 @@ impl<'cx, 'gcx, 'tcx> TypeOutlives<'cx, 'gcx, 'tcx> { ) -> Vec<ty::Region<'tcx>> { let tcx = self.tcx(); - // To start, collect bounds from user: + // To start, collect bounds from user environment. Note that + // parameter environments are already elaborated, so we don't + // have to worry about that. Comparing using `==` is a bit + // dubious for projections, but it will work for simple cases + // like `T` and `T::Item`. It may not work as well for things + // like `<T as Foo<'a>>::Item`. let mut param_bounds = - tcx.required_region_bounds(generic.to_ty(tcx), self.param_env.caller_bounds.to_vec()); + self.collect_outlives_from_predicate_list( + generic.to_ty(tcx), + self.param_env.caller_bounds); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -559,10 +566,31 @@ impl<'cx, 'gcx, 'tcx> TypeOutlives<'cx, 'gcx, 'tcx> { let trait_predicates = tcx.predicates_of(trait_def_id); let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id); let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs); - traits::elaborate_predicates(tcx, trait_predicates.predicates) - .filter_map(|p| p.to_opt_type_outlives()) - .filter_map(|p| tcx.no_late_bound_regions(&p)) - .filter(|p| p.0 == identity_proj) + self.collect_outlives_from_predicate_list( + identity_proj, + traits::elaborate_predicates(tcx, trait_predicates.predicates)) + } + + /// Searches through a predicate list for a predicate `T: 'a`. + /// + /// Careful: does not elaborate predicates, and just uses `==` + /// when comparing `ty` for equality, so `ty` must be something + /// that does not involve inference variables and where you + /// otherwise want a precise match. + fn collect_outlives_from_predicate_list<I, P>( + &self, + ty: Ty<'tcx>, + predicates: I, + ) -> Vec<ty::Region<'tcx>> + where + I: IntoIterator<Item = P>, + P: AsRef<ty::Predicate<'tcx>>, + { + predicates + .into_iter() + .filter_map(|p| p.as_ref().to_opt_type_outlives()) + .filter_map(|p| self.tcx().no_late_bound_regions(&p)) + .filter(|p| p.0 == ty) .map(|p| p.1) .collect() } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8973d1e0c5a..a9efb042f3d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -904,6 +904,12 @@ pub enum Predicate<'tcx> { ConstEvaluatable(DefId, &'tcx Substs<'tcx>), } +impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> { + fn as_ref(&self) -> &Predicate<'tcx> { + self + } +} + impl<'a, 'gcx, 'tcx> Predicate<'tcx> { /// Performs a substitution suitable for going from a /// poly-trait-ref to supertraits that must hold if that |
