From 1f33145ae91cbe095616c92ace63c93b61e5b4e9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 12 Nov 2017 05:04:26 -0500 Subject: [PATCH] make `no_late_bound_regions` a method on `Binder` --- src/librustc/infer/outlives/implied_bounds.rs | 4 ++-- src/librustc/infer/outlives/obligations.rs | 2 +- src/librustc/traits/fulfill.rs | 4 ++-- src/librustc/traits/project.rs | 2 +- src/librustc/traits/select.rs | 4 ++-- src/librustc/ty/fold.rs | 10 ---------- src/librustc/ty/sty.rs | 20 +++++++++++++++++++ src/librustc_mir/shim.rs | 2 +- src/librustc_mir/transform/lower_128bit.rs | 2 +- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/intrinsic.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- 12 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/librustc/infer/outlives/implied_bounds.rs b/src/librustc/infer/outlives/implied_bounds.rs index ae6961a0713..452ceddd7d6 100644 --- a/src/librustc/infer/outlives/implied_bounds.rs +++ b/src/librustc/infer/outlives/implied_bounds.rs @@ -126,7 +126,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { } ty::Predicate::RegionOutlives(ref data) => { - match tcx.no_late_bound_regions(data) { + match data.no_late_bound_regions() { None => vec![], Some(ty::OutlivesPredicate(r_a, r_b)) => { vec![ImpliedBound::RegionSubRegion(r_b, r_a)] @@ -135,7 +135,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { } ty::Predicate::TypeOutlives(ref data) => { - match tcx.no_late_bound_regions(data) { + match data.no_late_bound_regions() { None => vec![], Some(ty::OutlivesPredicate(ty_a, r_b)) => { let ty_a = self.resolve_type_vars_if_possible(&ty_a); diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index 3c3aba372fb..07eacde0aab 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -604,7 +604,7 @@ impl<'cx, 'gcx, 'tcx> TypeOutlives<'cx, 'gcx, '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_map(|p| p.no_late_bound_regions()) .filter(|p| p.0 == ty) .map(|p| p.1) .collect() diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index f56c3853de0..93e33836818 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -400,14 +400,14 @@ fn process_predicate<'a, 'gcx, 'tcx>( ty::Predicate::TypeOutlives(ref binder) => { // Check if there are higher-ranked regions. - match selcx.tcx().no_late_bound_regions(binder) { + match binder.no_late_bound_regions() { // If there are, inspect the underlying type further. None => { // Convert from `Binder>` to `Binder`. let binder = binder.map_bound_ref(|pred| pred.0); // Check if the type has any bound regions. - match selcx.tcx().no_late_bound_regions(&binder) { + match binder.no_late_bound_regions() { // If so, this obligation is an error (for now). Eventually we should be // able to support additional cases here, like `for<'a> &'a str: 'a`. None => { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 0cc755dc427..429771cca98 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1559,7 +1559,7 @@ impl<'cx, 'gcx, 'tcx> ProjectionCacheKey<'tcx> { let infcx = selcx.infcx(); // We don't do cross-snapshot caching of obligations with escaping regions, // so there's no cache key to use - infcx.tcx.no_late_bound_regions(&predicate) + predicate.no_late_bound_regions() .map(|predicate| ProjectionCacheKey { // We don't attempt to match up with a specific type-variable state // from a specific call to `opt_normalize_projection_type` - if diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 4bc3e2dd4d8..91e6c4270b3 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1834,7 +1834,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // T: Trait // so it seems ok if we (conservatively) fail to accept that `Unsize` // obligation above. Should be possible to extend this in the future. - let source = match self.tcx().no_late_bound_regions(&obligation.self_ty()) { + let source = match obligation.self_ty().no_late_bound_regions() { Some(t) => t, None => { // Don't add any candidates if there are bound regions. @@ -2784,7 +2784,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // assemble_candidates_for_unsizing should ensure there are no late bound // regions here. See the comment there for more details. let source = self.infcx.shallow_resolve( - tcx.no_late_bound_regions(&obligation.self_ty()).unwrap()); + obligation.self_ty().no_late_bound_regions().unwrap()); let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1); let target = self.infcx.shallow_resolve(target); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index bee11999223..65859603183 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -364,16 +364,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Binder(value) } - pub fn no_late_bound_regions(self, value: &Binder) -> Option - where T : TypeFoldable<'tcx> - { - if value.0.has_escaping_regions() { - None - } else { - Some(value.0.clone()) - } - } - /// Returns a set of all late-bound regions that are constrained /// by `value`, meaning that if we instantiate those LBR with /// variables and equate `value` with something else, those diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index caf78309cc2..c115b573a1c 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -680,6 +680,26 @@ impl Binder { { ty::Binder(f(self.0)) } + + /// Unwraps and returns the value within, but only if it contains + /// no bound regions at all. (In other words, if this binder -- + /// and indeed any enclosing binder -- doesn't bind anything at + /// all.) Otherwise, returns `None`. + /// + /// (One could imagine having a method that just unwraps a single + /// binder, but permits late-bound regions bound by enclosing + /// binders, but that would require adjusting the debruijn + /// indices, and given the shallow binding structure we often use, + /// would not be that useful.) + pub fn no_late_bound_regions<'tcx>(self) -> Option + where T : TypeFoldable<'tcx> + { + if self.skip_binder().has_escaping_regions() { + None + } else { + Some(self.skip_binder().clone()) + } + } } /// Represents the projection of an associated type. In explicit UFCS diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 9ca044b7648..46193dedf89 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -833,7 +833,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, let tcx = infcx.tcx; let gcx = tcx.global_tcx(); let def_id = tcx.hir.local_def_id(ctor_id); - let sig = gcx.no_late_bound_regions(&gcx.fn_sig(def_id)) + let sig = gcx.fn_sig(def_id).no_late_bound_regions() .expect("LBR in ADT constructor signature"); let sig = gcx.erase_regions(&sig); let param_env = gcx.param_env(def_id); diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs index 7027d827c84..f8c45dd3d25 100644 --- a/src/librustc_mir/transform/lower_128bit.rs +++ b/src/librustc_mir/transform/lower_128bit.rs @@ -144,7 +144,7 @@ fn check_lang_item_type<'a, 'tcx, D>( { let did = tcx.require_lang_item(lang_item); let poly_sig = tcx.fn_sig(did); - let sig = tcx.no_late_bound_regions(&poly_sig).unwrap(); + let sig = poly_sig.no_late_bound_regions().unwrap(); let lhs_ty = lhs.ty(local_decls, tcx); let rhs_ty = rhs.ty(local_decls, tcx); let place_ty = place.ty(local_decls, tcx).to_ty(tcx); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index f03f782ebb4..d5e4aa69c5b 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -800,7 +800,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id); // Replace constructor type with constructed type for tuple struct patterns. let pat_ty = pat_ty.fn_sig(tcx).output(); - let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type"); + let pat_ty = pat_ty.no_late_bound_regions().expect("expected fn type"); self.demand_eqtype(pat.span, expected, pat_ty); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index c1adb0e65a4..23243c3ad66 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -389,7 +389,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut structural_to_nomimal = FxHashMap(); let sig = tcx.fn_sig(def_id); - let sig = tcx.no_late_bound_regions(&sig).unwrap(); + let sig = sig.no_late_bound_regions().unwrap(); if intr.inputs.len() != sig.inputs().len() { span_err!(tcx.sess, it.span, E0444, "platform-specific intrinsic has invalid number of \ diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7de29868d43..b754c981b21 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> { poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> { - if let Some(trait_ref) = self.tcx().no_late_bound_regions(&poly_trait_ref) { + if let Some(trait_ref) = poly_trait_ref.no_late_bound_regions() { self.tcx().mk_projection(item_def_id, trait_ref.substs) } else { // no late-bound regions, we can just ignore the binder