Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Move required_region_bounds to rustc::infer::opaque_types.
  • Loading branch information
cjgillot committed Jan 7, 2020
1 parent 24d09c7 commit 86ec4b5
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 68 deletions.
69 changes: 67 additions & 2 deletions src/librustc/infer/opaque_types/mod.rs
Expand Up @@ -350,7 +350,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
debug!("constrain_opaque_type: bounds={:#?}", bounds);
let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);

let required_region_bounds = tcx.required_region_bounds(opaque_type, bounds.predicates);
let required_region_bounds =
required_region_bounds(tcx, opaque_type, bounds.predicates);
debug_assert!(!required_region_bounds.is_empty());

for required_region in required_region_bounds {
Expand Down Expand Up @@ -1133,7 +1134,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {

debug!("instantiate_opaque_types: bounds={:?}", bounds);

let required_region_bounds = tcx.required_region_bounds(ty, bounds.predicates.clone());
let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone());
debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);

// Make sure that we are in fact defining the *entire* type
Expand Down Expand Up @@ -1228,3 +1229,67 @@ pub fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: DefId, opaque_hir_id: hir
);
res
}

/// Given a set of predicates that apply to an object type, returns
/// the region bounds that the (erased) `Self` type must
/// outlive. Precisely *because* the `Self` type is erased, the
/// parameter `erased_self_ty` must be supplied to indicate what type
/// has been used to represent `Self` in the predicates
/// themselves. This should really be a unique type; `FreshTy(0)` is a
/// popular choice.
///
/// N.B., in some cases, particularly around higher-ranked bounds,
/// this function returns a kind of conservative approximation.
/// That is, all regions returned by this function are definitely
/// required, but there may be other region bounds that are not
/// returned, as well as requirements like `for<'a> T: 'a`.
///
/// Requires that trait definitions have been processed so that we can
/// elaborate predicates and walk supertraits.
//
// FIXME: callers may only have a `&[Predicate]`, not a `Vec`, so that's
// what this code should accept.
crate fn required_region_bounds(
tcx: TyCtxt<'tcx>,
erased_self_ty: Ty<'tcx>,
predicates: Vec<ty::Predicate<'tcx>>,
) -> Vec<ty::Region<'tcx>> {
debug!(
"required_region_bounds(erased_self_ty={:?}, predicates={:?})",
erased_self_ty, predicates
);

assert!(!erased_self_ty.has_escaping_bound_vars());

traits::elaborate_predicates(tcx, predicates)
.filter_map(|predicate| {
match predicate {
ty::Predicate::Projection(..)
| ty::Predicate::Trait(..)
| ty::Predicate::Subtype(..)
| ty::Predicate::WellFormed(..)
| ty::Predicate::ObjectSafe(..)
| ty::Predicate::ClosureKind(..)
| ty::Predicate::RegionOutlives(..)
| ty::Predicate::ConstEvaluatable(..) => None,
ty::Predicate::TypeOutlives(predicate) => {
// Search for a bound of the form `erased_self_ty
// : 'a`, but be wary of something like `for<'a>
// erased_self_ty : 'a` (we interpret a
// higher-ranked bound like that as 'static,
// though at present the code in `fulfill.rs`
// considers such bounds to be unsatisfiable, so
// it's kind of a moot point since you could never
// construct such an object, but this seems
// correct even if that code changes).
let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
if t == &erased_self_ty && !r.has_escaping_bound_vars() {
Some(*r)
} else {
None
}
}
}
})
.collect()
}
5 changes: 3 additions & 2 deletions src/librustc/traits/wf.rs
@@ -1,3 +1,4 @@
use crate::infer::opaque_types::required_region_bounds;
use crate::infer::InferCtxt;
use crate::middle::lang_items;
use crate::traits::{self, AssocTypeBoundData};
Expand Down Expand Up @@ -668,7 +669,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
/// from the declarations of `SomeTrait`, `Send`, and friends -- if
/// they declare `trait SomeTrait : 'static`, for example, then
/// `'static` would appear in the list. The hard work is done by
/// `ty::required_region_bounds`, see that for more information.
/// `infer::required_region_bounds`, see that for more information.
pub fn object_region_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
existential_predicates: ty::Binder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>,
Expand All @@ -689,7 +690,7 @@ pub fn object_region_bounds<'tcx>(
})
.collect();

tcx.required_region_bounds(open_ty, predicates)
required_region_bounds(tcx, open_ty, predicates)
}

/// Find the span of a generic bound affecting an associated type.
Expand Down
64 changes: 0 additions & 64 deletions src/librustc/ty/util.rs
Expand Up @@ -393,70 +393,6 @@ impl<'tcx> TyCtxt<'tcx> {
(a, b)
}

/// Given a set of predicates that apply to an object type, returns
/// the region bounds that the (erased) `Self` type must
/// outlive. Precisely *because* the `Self` type is erased, the
/// parameter `erased_self_ty` must be supplied to indicate what type
/// has been used to represent `Self` in the predicates
/// themselves. This should really be a unique type; `FreshTy(0)` is a
/// popular choice.
///
/// N.B., in some cases, particularly around higher-ranked bounds,
/// this function returns a kind of conservative approximation.
/// That is, all regions returned by this function are definitely
/// required, but there may be other region bounds that are not
/// returned, as well as requirements like `for<'a> T: 'a`.
///
/// Requires that trait definitions have been processed so that we can
/// elaborate predicates and walk supertraits.
//
// FIXME: callers may only have a `&[Predicate]`, not a `Vec`, so that's
// what this code should accept.
pub fn required_region_bounds(
self,
erased_self_ty: Ty<'tcx>,
predicates: Vec<ty::Predicate<'tcx>>,
) -> Vec<ty::Region<'tcx>> {
debug!(
"required_region_bounds(erased_self_ty={:?}, predicates={:?})",
erased_self_ty, predicates
);

assert!(!erased_self_ty.has_escaping_bound_vars());

traits::elaborate_predicates(self, predicates)
.filter_map(|predicate| {
match predicate {
ty::Predicate::Projection(..)
| ty::Predicate::Trait(..)
| ty::Predicate::Subtype(..)
| ty::Predicate::WellFormed(..)
| ty::Predicate::ObjectSafe(..)
| ty::Predicate::ClosureKind(..)
| ty::Predicate::RegionOutlives(..)
| ty::Predicate::ConstEvaluatable(..) => None,
ty::Predicate::TypeOutlives(predicate) => {
// Search for a bound of the form `erased_self_ty
// : 'a`, but be wary of something like `for<'a>
// erased_self_ty : 'a` (we interpret a
// higher-ranked bound like that as 'static,
// though at present the code in `fulfill.rs`
// considers such bounds to be unsatisfiable, so
// it's kind of a moot point since you could never
// construct such an object, but this seems
// correct even if that code changes).
let ty::OutlivesPredicate(ref t, ref r) = predicate.skip_binder();
if t == &erased_self_ty && !r.has_escaping_bound_vars() {
Some(*r)
} else {
None
}
}
}
})
.collect()
}

/// Calculate the destructor of a given type.
pub fn calculate_dtor(
self,
Expand Down

0 comments on commit 86ec4b5

Please sign in to comment.