Create a visitor for TypeFoldables and use it to implement RegionEscape and HasTypeFlags (fixes #20298)
This commit is contained in:
parent
5daa75373d
commit
f9808ea4b4
19 changed files with 534 additions and 690 deletions
|
|
@ -404,7 +404,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn fully_normalize<T>(&self, value: &T) -> Result<T,ErrorReported>
|
||||
where T : TypeFoldable<'tcx> + ty::HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
let value =
|
||||
traits::fully_normalize(self.infcx,
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ impl<'cx, 'tcx> ty::fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
_ => {
|
||||
ty::fold::super_fold_ty(self, t)
|
||||
t.fold_subitems_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
|
|||
ty::TyTuple(..) |
|
||||
ty::TyProjection(..) |
|
||||
ty::TyParam(..) => {
|
||||
ty::fold::super_fold_ty(self, t)
|
||||
t.fold_subitems_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -512,7 +512,7 @@ pub struct CombinedSnapshot {
|
|||
}
|
||||
|
||||
pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
debug!("normalize_associated_type(t={:?})", value);
|
||||
|
||||
|
|
@ -546,7 +546,7 @@ pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
|
|||
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
|
||||
result: &T)
|
||||
-> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
match drain_fulfillment_cx(infcx, fulfill_cx, result) {
|
||||
Ok(v) => v,
|
||||
|
|
@ -570,7 +570,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
|
|||
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
|
||||
result: &T)
|
||||
-> Result<T,Vec<traits::FulfillmentError<'tcx>>>
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
debug!("drain_fulfillment_cx(result={:?})",
|
||||
result);
|
||||
|
|
@ -929,7 +929,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
snapshot: &CombinedSnapshot,
|
||||
value: &T)
|
||||
-> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
/*! See `higher_ranked::plug_leaks` */
|
||||
|
||||
|
|
@ -1201,7 +1201,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
|
||||
where T: TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T: TypeFoldable<'tcx>
|
||||
{
|
||||
/*!
|
||||
* Where possible, replaces type/int/float variables in
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx
|
|||
t // micro-optimize -- if there is nothing in this type that this fold affects...
|
||||
} else {
|
||||
let t0 = self.infcx.shallow_resolve(t);
|
||||
ty::fold::super_fold_ty(self, t0)
|
||||
t0.fold_subitems_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeAndRegionResolver
|
|||
t // micro-optimize -- if there is nothing in this type that this fold affects...
|
||||
} else {
|
||||
let t0 = self.infcx.shallow_resolve(t);
|
||||
ty::fold::super_fold_ty(self, t0)
|
||||
t0.fold_subitems_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +133,7 @@ impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
|
|||
t));
|
||||
}
|
||||
_ => {
|
||||
ty::fold::super_fold_ty(self, t)
|
||||
t.fold_subitems_with(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -674,7 +674,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
|||
self.ty_for_param(p, t)
|
||||
}
|
||||
_ => {
|
||||
ty::fold::super_fold_ty(self, t)
|
||||
t.fold_subitems_with(self)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
|
|||
pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
|
||||
obligation: &Obligation<'tcx, T>)
|
||||
-> !
|
||||
where T: fmt::Display + TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T: fmt::Display + TypeFoldable<'tcx>
|
||||
{
|
||||
let predicate =
|
||||
infcx.resolve_type_vars_if_possible(&obligation.predicate);
|
||||
|
|
|
|||
|
|
@ -470,7 +470,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
|
|||
cause: ObligationCause<'tcx>,
|
||||
value: &T)
|
||||
-> Result<T, Vec<FulfillmentError<'tcx>>>
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
debug!("normalize_param_env(value={:?})", value);
|
||||
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
|
|||
cause: ObligationCause<'tcx>,
|
||||
value: &T)
|
||||
-> Normalized<'tcx, T>
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
normalize_with_depth(selcx, cause, 0, value)
|
||||
}
|
||||
|
|
@ -213,7 +213,7 @@ pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tc
|
|||
depth: usize,
|
||||
value: &T)
|
||||
-> Normalized<'tcx, T>
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth);
|
||||
let result = normalizer.fold(value);
|
||||
|
|
@ -245,7 +245,7 @@ impl<'a,'b,'tcx> AssociatedTypeNormalizer<'a,'b,'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn fold<T:TypeFoldable<'tcx> + HasTypeFlags>(&mut self, value: &T) -> T {
|
||||
fn fold<T:TypeFoldable<'tcx>>(&mut self, value: &T) -> T {
|
||||
let value = self.selcx.infcx().resolve_type_vars_if_possible(value);
|
||||
|
||||
if !value.has_projection_types() {
|
||||
|
|
@ -273,7 +273,7 @@ impl<'a,'b,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'b,'tcx> {
|
|||
// normalize it when we instantiate those bound regions (which
|
||||
// should occur eventually).
|
||||
|
||||
let ty = ty::fold::super_fold_ty(self, ty);
|
||||
let ty = ty.fold_subitems_with(self);
|
||||
match ty.sty {
|
||||
ty::TyProjection(ref data) if !data.has_escaping_regions() => { // (*)
|
||||
|
||||
|
|
|
|||
|
|
@ -965,7 +965,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
match *candidate {
|
||||
Ok(Some(_)) | Err(_) => true,
|
||||
Ok(None) => {
|
||||
cache_fresh_trait_pred.0.input_types().has_infer_types()
|
||||
cache_fresh_trait_pred.0.trait_ref.substs.types.has_infer_types()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@
|
|||
|
||||
use middle::traits;
|
||||
use middle::traits::project::Normalized;
|
||||
use middle::ty::{HasTypeFlags, TypeFlags, RegionEscape};
|
||||
use middle::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
|
||||
use std::fmt;
|
||||
|
||||
|
|
@ -131,71 +130,6 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, P: RegionEscape> RegionEscape for traits::Obligation<'tcx,P> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.predicate.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: HasTypeFlags> HasTypeFlags for traits::Obligation<'tcx, T> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.predicate.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: HasTypeFlags> HasTypeFlags for Normalized<'tcx, T> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.value.has_type_flags(flags) ||
|
||||
self.obligations.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableImplData<'tcx, N> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.substs.has_type_flags(flags) ||
|
||||
self.nested.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableClosureData<'tcx, N> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.substs.has_type_flags(flags) ||
|
||||
self.nested.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableDefaultImplData<N> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.nested.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::VtableBuiltinData<N> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.nested.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for traits::VtableObjectData<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.upcast_trait_ref.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: HasTypeFlags> HasTypeFlags for traits::Vtable<'tcx, N> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
match *self {
|
||||
traits::VtableImpl(ref v) => v.has_type_flags(flags),
|
||||
traits::VtableDefaultImpl(ref t) => t.has_type_flags(flags),
|
||||
traits::VtableClosure(ref d) => d.has_type_flags(flags),
|
||||
traits::VtableFnPointer(ref d) => d.has_type_flags(flags),
|
||||
traits::VtableParam(ref n) => n.has_type_flags(flags),
|
||||
traits::VtableBuiltin(ref d) => d.has_type_flags(flags),
|
||||
traits::VtableObject(ref d) => d.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O>
|
||||
{
|
||||
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Obligation<'tcx, O> {
|
||||
|
|
@ -205,6 +139,10 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
|
|||
predicate: self.predicate.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.predicate.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<'tcx, N> {
|
||||
|
|
@ -215,6 +153,10 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<
|
|||
nested: self.nested.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.substs.visit_with(visitor) || self.nested.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureData<'tcx, N> {
|
||||
|
|
@ -225,6 +167,10 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableClosureDa
|
|||
nested: self.nested.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.substs.visit_with(visitor) || self.nested.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> {
|
||||
|
|
@ -234,6 +180,10 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultIm
|
|||
nested: self.nested.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.nested.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
|
||||
|
|
@ -242,6 +192,10 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinDa
|
|||
nested: self.nested.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.nested.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
|
||||
|
|
@ -251,6 +205,10 @@ impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
|
|||
vtable_base: self.vtable_base
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.upcast_trait_ref.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
|
||||
|
|
@ -269,6 +227,18 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
|
|||
traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match *self {
|
||||
traits::VtableImpl(ref v) => v.visit_with(visitor),
|
||||
traits::VtableDefaultImpl(ref t) => t.visit_with(visitor),
|
||||
traits::VtableClosure(ref d) => d.visit_with(visitor),
|
||||
traits::VtableFnPointer(ref d) => d.visit_with(visitor),
|
||||
traits::VtableParam(ref n) => n.visit_with(visitor),
|
||||
traits::VtableBuiltin(ref d) => d.visit_with(visitor),
|
||||
traits::VtableObject(ref d) => d.visit_with(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> {
|
||||
|
|
@ -278,4 +248,8 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> {
|
|||
obligations: self.obligations.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.value.visit_with(visitor) || self.obligations.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,41 +14,51 @@
|
|||
//! instance of a "folder" (a type which implements `TypeFolder`). Then
|
||||
//! the setup is intended to be:
|
||||
//!
|
||||
//! T.fold_with(F) --calls--> F.fold_T(T) --calls--> super_fold_T(F, T)
|
||||
//! T.fold_with(F) --calls--> F.fold_T(T) --calls--> T.fold_subitems_with(F)
|
||||
//!
|
||||
//! This way, when you define a new folder F, you can override
|
||||
//! `fold_T()` to customize the behavior, and invoke `super_fold_T()`
|
||||
//! `fold_T()` to customize the behavior, and invoke `T.fold_subitems_with()`
|
||||
//! to get the original behavior. Meanwhile, to actually fold
|
||||
//! something, you can just write `T.fold_with(F)`, which is
|
||||
//! convenient. (Note that `fold_with` will also transparently handle
|
||||
//! things like a `Vec<T>` where T is foldable and so on.)
|
||||
//!
|
||||
//! In this ideal setup, the only function that actually *does*
|
||||
//! anything is `super_fold_T`, which traverses the type `T`. Moreover,
|
||||
//! `super_fold_T` should only ever call `T.fold_with()`.
|
||||
//! anything is `T.fold_subitems_with()`, which traverses the type `T`.
|
||||
//! Moreover, `T.fold_subitems_with()` should only ever call `T.fold_with()`.
|
||||
//!
|
||||
//! In some cases, we follow a degenerate pattern where we do not have
|
||||
//! a `fold_T` nor `super_fold_T` method. Instead, `T.fold_with`
|
||||
//! traverses the structure directly. This is suboptimal because the
|
||||
//! behavior cannot be overridden, but it's much less work to implement.
|
||||
//! If you ever *do* need an override that doesn't exist, it's not hard
|
||||
//! to convert the degenerate pattern into the proper thing.
|
||||
//! a `fold_T` method. Instead, `T.fold_with` traverses the structure directly.
|
||||
//! This is suboptimal because the behavior cannot be overridden, but it's
|
||||
//! much less work to implement. If you ever *do* need an override that
|
||||
//! doesn't exist, it's not hard to convert the degenerate pattern into the
|
||||
//! proper thing.
|
||||
//!
|
||||
//! A `TypeFoldable` T can also be visited by a `TypeVisitor` V using similar setup:
|
||||
//! T.visit_with(V) --calls--> V.visit_T(T) --calls--> T.visit_subitems_with(V).
|
||||
//! These methods return true to indicate that the visitor has found what it is looking for
|
||||
//! and does not need to visit anything else.
|
||||
|
||||
use middle::region;
|
||||
use middle::subst;
|
||||
use middle::ty::adjustment;
|
||||
use middle::ty::{self, Binder, Ty, RegionEscape};
|
||||
use middle::ty::{self, Binder, Ty, RegionEscape, HasTypeFlags};
|
||||
|
||||
use std::fmt;
|
||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Two generic traits
|
||||
|
||||
/// The TypeFoldable trait is implemented for every type that can be folded.
|
||||
/// Basically, every type that has a corresponding method in TypeFolder.
|
||||
pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self;
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
self.fold_with(folder)
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool;
|
||||
fn visit_subitems_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
/// The TypeFolder trait defines the actual *folding*. There is a
|
||||
|
|
@ -74,248 +84,77 @@ pub trait TypeFolder<'tcx> : Sized {
|
|||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
// FIXME(#20526) this should replace `enter_region_binder`/`exit_region_binder`.
|
||||
super_fold_binder(self, t)
|
||||
t.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
super_fold_ty(self, t)
|
||||
t.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_mt(&mut self, t: &ty::TypeAndMut<'tcx>) -> ty::TypeAndMut<'tcx> {
|
||||
super_fold_mt(self, t)
|
||||
t.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_trait_ref(&mut self, t: &ty::TraitRef<'tcx>) -> ty::TraitRef<'tcx> {
|
||||
super_fold_trait_ref(self, t)
|
||||
t.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_substs(&mut self,
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> subst::Substs<'tcx> {
|
||||
super_fold_substs(self, substs)
|
||||
substs.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_fn_sig(&mut self,
|
||||
sig: &ty::FnSig<'tcx>)
|
||||
-> ty::FnSig<'tcx> {
|
||||
super_fold_fn_sig(self, sig)
|
||||
sig.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_output(&mut self,
|
||||
output: &ty::FnOutput<'tcx>)
|
||||
-> ty::FnOutput<'tcx> {
|
||||
super_fold_output(self, output)
|
||||
output.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_bare_fn_ty(&mut self,
|
||||
fty: &ty::BareFnTy<'tcx>)
|
||||
-> ty::BareFnTy<'tcx>
|
||||
{
|
||||
super_fold_bare_fn_ty(self, fty)
|
||||
fty.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_closure_ty(&mut self,
|
||||
fty: &ty::ClosureTy<'tcx>)
|
||||
-> ty::ClosureTy<'tcx> {
|
||||
super_fold_closure_ty(self, fty)
|
||||
fty.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
|
||||
r
|
||||
r.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
|
||||
-> ty::ExistentialBounds<'tcx> {
|
||||
super_fold_existential_bounds(self, s)
|
||||
s.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_autoref(&mut self, ar: &adjustment::AutoRef<'tcx>)
|
||||
-> adjustment::AutoRef<'tcx> {
|
||||
super_fold_autoref(self, ar)
|
||||
}
|
||||
|
||||
fn fold_item_substs(&mut self, i: ty::ItemSubsts<'tcx>) -> ty::ItemSubsts<'tcx> {
|
||||
super_fold_item_substs(self, i)
|
||||
ar.fold_subitems_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// "super" routines: these are the default implementations for TypeFolder.
|
||||
//
|
||||
// They should invoke `foo.fold_with()` to do recursive folding.
|
||||
pub trait TypeVisitor<'tcx> : Sized {
|
||||
fn enter_region_binder(&mut self) { }
|
||||
fn exit_region_binder(&mut self) { }
|
||||
|
||||
pub fn super_fold_binder<'tcx, T, U>(this: &mut T,
|
||||
binder: &Binder<U>)
|
||||
-> Binder<U>
|
||||
where T : TypeFolder<'tcx>, U : TypeFoldable<'tcx>
|
||||
{
|
||||
this.enter_region_binder();
|
||||
let result = Binder(binder.0.fold_with(this));
|
||||
this.exit_region_binder();
|
||||
result
|
||||
}
|
||||
|
||||
pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
ty: Ty<'tcx>)
|
||||
-> Ty<'tcx> {
|
||||
let sty = match ty.sty {
|
||||
ty::TyBox(typ) => {
|
||||
ty::TyBox(typ.fold_with(this))
|
||||
}
|
||||
ty::TyRawPtr(ref tm) => {
|
||||
ty::TyRawPtr(tm.fold_with(this))
|
||||
}
|
||||
ty::TyArray(typ, sz) => {
|
||||
ty::TyArray(typ.fold_with(this), sz)
|
||||
}
|
||||
ty::TySlice(typ) => {
|
||||
ty::TySlice(typ.fold_with(this))
|
||||
}
|
||||
ty::TyEnum(tid, ref substs) => {
|
||||
let substs = substs.fold_with(this);
|
||||
ty::TyEnum(tid, this.tcx().mk_substs(substs))
|
||||
}
|
||||
ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
|
||||
ty::TyTrait(box ty::TraitTy {
|
||||
principal: principal.fold_with(this),
|
||||
bounds: bounds.fold_with(this),
|
||||
})
|
||||
}
|
||||
ty::TyTuple(ref ts) => {
|
||||
ty::TyTuple(ts.fold_with(this))
|
||||
}
|
||||
ty::TyBareFn(opt_def_id, ref f) => {
|
||||
let bfn = f.fold_with(this);
|
||||
ty::TyBareFn(opt_def_id, this.tcx().mk_bare_fn(bfn))
|
||||
}
|
||||
ty::TyRef(r, ref tm) => {
|
||||
let r = r.fold_with(this);
|
||||
ty::TyRef(this.tcx().mk_region(r), tm.fold_with(this))
|
||||
}
|
||||
ty::TyStruct(did, ref substs) => {
|
||||
let substs = substs.fold_with(this);
|
||||
ty::TyStruct(did, this.tcx().mk_substs(substs))
|
||||
}
|
||||
ty::TyClosure(did, ref substs) => {
|
||||
let s = substs.fold_with(this);
|
||||
ty::TyClosure(did, s)
|
||||
}
|
||||
ty::TyProjection(ref data) => {
|
||||
ty::TyProjection(data.fold_with(this))
|
||||
}
|
||||
ty::TyBool | ty::TyChar | ty::TyStr |
|
||||
ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) |
|
||||
ty::TyError | ty::TyInfer(_) |
|
||||
ty::TyParam(..) => {
|
||||
ty.sty.clone()
|
||||
}
|
||||
};
|
||||
this.tcx().mk_ty(sty)
|
||||
}
|
||||
|
||||
pub fn super_fold_substs<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> subst::Substs<'tcx> {
|
||||
let regions = match substs.regions {
|
||||
subst::ErasedRegions => {
|
||||
subst::ErasedRegions
|
||||
}
|
||||
subst::NonerasedRegions(ref regions) => {
|
||||
subst::NonerasedRegions(regions.fold_with(this))
|
||||
}
|
||||
};
|
||||
|
||||
subst::Substs { regions: regions,
|
||||
types: substs.types.fold_with(this) }
|
||||
}
|
||||
|
||||
pub fn super_fold_fn_sig<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
sig: &ty::FnSig<'tcx>)
|
||||
-> ty::FnSig<'tcx>
|
||||
{
|
||||
ty::FnSig { inputs: sig.inputs.fold_with(this),
|
||||
output: sig.output.fold_with(this),
|
||||
variadic: sig.variadic }
|
||||
}
|
||||
|
||||
pub fn super_fold_output<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
output: &ty::FnOutput<'tcx>)
|
||||
-> ty::FnOutput<'tcx> {
|
||||
match *output {
|
||||
ty::FnConverging(ref ty) => ty::FnConverging(ty.fold_with(this)),
|
||||
ty::FnDiverging => ty::FnDiverging
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
||||
t.visit_subitems_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn super_fold_bare_fn_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
fty: &ty::BareFnTy<'tcx>)
|
||||
-> ty::BareFnTy<'tcx>
|
||||
{
|
||||
ty::BareFnTy { sig: fty.sig.fold_with(this),
|
||||
abi: fty.abi,
|
||||
unsafety: fty.unsafety }
|
||||
}
|
||||
|
||||
pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
fty: &ty::ClosureTy<'tcx>)
|
||||
-> ty::ClosureTy<'tcx>
|
||||
{
|
||||
ty::ClosureTy {
|
||||
sig: fty.sig.fold_with(this),
|
||||
unsafety: fty.unsafety,
|
||||
abi: fty.abi,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn super_fold_trait_ref<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
t: &ty::TraitRef<'tcx>)
|
||||
-> ty::TraitRef<'tcx>
|
||||
{
|
||||
let substs = t.substs.fold_with(this);
|
||||
ty::TraitRef {
|
||||
def_id: t.def_id,
|
||||
substs: this.tcx().mk_substs(substs),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn super_fold_mt<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
mt: &ty::TypeAndMut<'tcx>)
|
||||
-> ty::TypeAndMut<'tcx> {
|
||||
ty::TypeAndMut {ty: mt.ty.fold_with(this),
|
||||
mutbl: mt.mutbl}
|
||||
}
|
||||
|
||||
pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
|
||||
this: &mut T,
|
||||
bounds: &ty::ExistentialBounds<'tcx>)
|
||||
-> ty::ExistentialBounds<'tcx>
|
||||
{
|
||||
ty::ExistentialBounds {
|
||||
region_bound: bounds.region_bound.fold_with(this),
|
||||
builtin_bounds: bounds.builtin_bounds,
|
||||
projection_bounds: bounds.projection_bounds.fold_with(this),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn super_fold_autoref<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
autoref: &adjustment::AutoRef<'tcx>)
|
||||
-> adjustment::AutoRef<'tcx>
|
||||
{
|
||||
match *autoref {
|
||||
adjustment::AutoPtr(r, m) => {
|
||||
let r = r.fold_with(this);
|
||||
adjustment::AutoPtr(this.tcx().mk_region(r), m)
|
||||
}
|
||||
adjustment::AutoUnsafe(m) => adjustment::AutoUnsafe(m)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn super_fold_item_substs<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
|
||||
substs: ty::ItemSubsts<'tcx>)
|
||||
-> ty::ItemSubsts<'tcx>
|
||||
{
|
||||
ty::ItemSubsts {
|
||||
substs: substs.substs.fold_with(this),
|
||||
fn visit_region(&mut self, r: ty::Region) -> bool {
|
||||
r.visit_subitems_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -333,7 +172,7 @@ impl<'a, 'tcx, F> TypeFolder<'tcx> for BottomUpFolder<'a, 'tcx, F> where
|
|||
fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let t1 = super_fold_ty(self, ty);
|
||||
let t1 = ty.fold_subitems_with(self);
|
||||
(self.fldop)(t1)
|
||||
}
|
||||
}
|
||||
|
|
@ -495,7 +334,7 @@ impl<'tcx> ty::ctxt<'tcx> {
|
|||
}
|
||||
|
||||
pub fn no_late_bound_regions<T>(&self, value: &Binder<T>) -> Option<T>
|
||||
where T : TypeFoldable<'tcx> + RegionEscape
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
if value.0.has_escaping_regions() {
|
||||
None
|
||||
|
|
@ -561,7 +400,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx>
|
|||
return t;
|
||||
}
|
||||
|
||||
super_fold_ty(self, t)
|
||||
t.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
|
||||
|
|
@ -612,7 +451,7 @@ impl<'tcx> ty::ctxt<'tcx> {
|
|||
Some(u) => return u
|
||||
}
|
||||
|
||||
let t_norm = ty::fold::super_fold_ty(self, ty);
|
||||
let t_norm = ty.fold_subitems_with(self);
|
||||
self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
|
||||
return t_norm;
|
||||
}
|
||||
|
|
@ -621,7 +460,7 @@ impl<'tcx> ty::ctxt<'tcx> {
|
|||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
let u = self.tcx().anonymize_late_bound_regions(t);
|
||||
ty::fold::super_fold_binder(self, &u)
|
||||
u.fold_subitems_with(self)
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region) -> ty::Region {
|
||||
|
|
@ -678,3 +517,65 @@ pub fn shift_regions<'tcx, T:TypeFoldable<'tcx>>(tcx: &ty::ctxt<'tcx>,
|
|||
shift_region(region, amount)
|
||||
}))
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> RegionEscape for T {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
struct RegionEscapeVisitor {
|
||||
depth: u32,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for RegionEscapeVisitor {
|
||||
fn enter_region_binder(&mut self) {
|
||||
self.depth += 1;
|
||||
}
|
||||
|
||||
fn exit_region_binder(&mut self) {
|
||||
self.depth -= 1;
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
|
||||
t.region_depth > self.depth
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region) -> bool {
|
||||
r.escapes_depth(self.depth)
|
||||
}
|
||||
}
|
||||
|
||||
self.visit_with(&mut RegionEscapeVisitor { depth: depth })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> HasTypeFlags for T {
|
||||
fn has_type_flags(&self, flags: ty::TypeFlags) -> bool {
|
||||
struct HasTypeFlagsVisitor {
|
||||
flags: ty::TypeFlags,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||
fn visit_ty(&mut self, t: Ty) -> bool {
|
||||
t.flags.get().intersects(self.flags)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region) -> bool {
|
||||
if self.flags.intersects(ty::TypeFlags::HAS_LOCAL_NAMES) {
|
||||
// does this represent a region that cannot be named
|
||||
// in a global way? used in fulfillment caching.
|
||||
match r {
|
||||
ty::ReStatic | ty::ReEmpty => {}
|
||||
_ => return true,
|
||||
}
|
||||
}
|
||||
if self.flags.intersects(ty::TypeFlags::HAS_RE_INFER) {
|
||||
match r {
|
||||
ty::ReVar(_) | ty::ReSkolemized(..) => { return true }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
self.visit_with(&mut HasTypeFlagsVisitor { flags: flags })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
use middle::def_id::DefId;
|
||||
use middle::subst::{ErasedRegions, NonerasedRegions, ParamSpace, Substs};
|
||||
use middle::ty::{self, HasTypeFlags, Ty};
|
||||
use middle::ty::{self, Ty};
|
||||
use middle::ty::error::{ExpectedFound, TypeError};
|
||||
use middle::ty::fold::TypeFoldable;
|
||||
use std::rc::Rc;
|
||||
|
|
@ -80,7 +80,7 @@ pub trait TypeRelation<'a,'tcx> : Sized {
|
|||
where T: Relate<'a,'tcx>;
|
||||
}
|
||||
|
||||
pub trait Relate<'a,'tcx>: TypeFoldable<'tcx> + HasTypeFlags {
|
||||
pub trait Relate<'a,'tcx>: TypeFoldable<'tcx> {
|
||||
fn relate<R:TypeRelation<'a,'tcx>>(relation: &mut R,
|
||||
a: &Self,
|
||||
b: &Self)
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@
|
|||
use middle::subst::{self, VecPerParamSpace};
|
||||
use middle::traits;
|
||||
use middle::ty::{self, TraitRef, Ty, TypeAndMut};
|
||||
use middle::ty::{HasTypeFlags, Lift, TypeFlags, RegionEscape};
|
||||
use middle::ty::fold::{TypeFoldable, TypeFolder};
|
||||
use middle::ty::Lift;
|
||||
use middle::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||
|
||||
use std::rc::Rc;
|
||||
use syntax::abi;
|
||||
|
|
@ -20,390 +20,6 @@ use syntax::ptr::P;
|
|||
|
||||
use rustc_front::hir;
|
||||
|
||||
// FIXME(#20298) -- all of these traits basically walk various
|
||||
// structures to test whether types/regions are reachable with various
|
||||
// properties. It should be possible to express them in terms of one
|
||||
// common "walker" trait or something.
|
||||
|
||||
impl<'tcx> RegionEscape for Ty<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.region_depth > depth
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::TraitTy<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.principal.has_regions_escaping_depth(depth) ||
|
||||
self.bounds.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::ExistentialBounds<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.region_bound.has_regions_escaping_depth(depth) ||
|
||||
self.projection_bounds.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::InstantiatedPredicates<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.predicates.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for subst::Substs<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.types.has_regions_escaping_depth(depth) ||
|
||||
self.regions.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::ClosureSubsts<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.func_substs.has_regions_escaping_depth(depth) ||
|
||||
self.upvar_tys.iter().any(|t| t.has_regions_escaping_depth(depth))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T:RegionEscape> RegionEscape for Vec<T> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.iter().any(|t| t.has_regions_escaping_depth(depth))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::FnSig<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.inputs.has_regions_escaping_depth(depth) ||
|
||||
self.output.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,T:RegionEscape> RegionEscape for VecPerParamSpace<T> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.iter_enumerated().any(|(space, _, t)| {
|
||||
if space == subst::FnSpace {
|
||||
t.has_regions_escaping_depth(depth+1)
|
||||
} else {
|
||||
t.has_regions_escaping_depth(depth)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::TypeScheme<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.ty.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl RegionEscape for ty::Region {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.escapes_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::GenericPredicates<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.predicates.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::Predicate<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
match *self {
|
||||
ty::Predicate::Trait(ref data) => data.has_regions_escaping_depth(depth),
|
||||
ty::Predicate::Equate(ref data) => data.has_regions_escaping_depth(depth),
|
||||
ty::Predicate::RegionOutlives(ref data) => data.has_regions_escaping_depth(depth),
|
||||
ty::Predicate::TypeOutlives(ref data) => data.has_regions_escaping_depth(depth),
|
||||
ty::Predicate::Projection(ref data) => data.has_regions_escaping_depth(depth),
|
||||
ty::Predicate::WellFormed(ty) => ty.has_regions_escaping_depth(depth),
|
||||
ty::Predicate::ObjectSafe(_trait_def_id) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for TraitRef<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) ||
|
||||
self.substs.regions.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for subst::RegionSubsts {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
match *self {
|
||||
subst::ErasedRegions => false,
|
||||
subst::NonerasedRegions(ref r) => {
|
||||
r.iter().any(|t| t.has_regions_escaping_depth(depth))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,T:RegionEscape> RegionEscape for ty::Binder<T> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.0.has_regions_escaping_depth(depth + 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::FnOutput<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
match *self {
|
||||
ty::FnConverging(t) => t.has_regions_escaping_depth(depth),
|
||||
ty::FnDiverging => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::EquatePredicate<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::TraitPredicate<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.trait_ref.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T:RegionEscape,U:RegionEscape> RegionEscape for ty::OutlivesPredicate<T,U> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::ProjectionPredicate<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.projection_ty.has_regions_escaping_depth(depth) ||
|
||||
self.ty.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> RegionEscape for ty::ProjectionTy<'tcx> {
|
||||
fn has_regions_escaping_depth(&self, depth: u32) -> bool {
|
||||
self.trait_ref.has_regions_escaping_depth(depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTypeFlags for () {
|
||||
fn has_type_flags(&self, _flags: TypeFlags) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,T:HasTypeFlags> HasTypeFlags for Vec<T> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self[..].has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,T:HasTypeFlags> HasTypeFlags for [T] {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.iter().any(|p| p.has_type_flags(flags))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,T:HasTypeFlags> HasTypeFlags for VecPerParamSpace<T> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.iter().any(|p| p.has_type_flags(flags))
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTypeFlags for abi::Abi {
|
||||
fn has_type_flags(&self, _flags: TypeFlags) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTypeFlags for hir::Unsafety {
|
||||
fn has_type_flags(&self, _flags: TypeFlags) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTypeFlags for ty::BuiltinBounds {
|
||||
fn has_type_flags(&self, _flags: TypeFlags) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::ClosureTy<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.sig.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::ClosureUpvar<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.ty.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::ExistentialBounds<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.projection_bounds.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::InstantiatedPredicates<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.predicates.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::Predicate<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
match *self {
|
||||
ty::Predicate::Trait(ref data) => data.has_type_flags(flags),
|
||||
ty::Predicate::Equate(ref data) => data.has_type_flags(flags),
|
||||
ty::Predicate::RegionOutlives(ref data) => data.has_type_flags(flags),
|
||||
ty::Predicate::TypeOutlives(ref data) => data.has_type_flags(flags),
|
||||
ty::Predicate::Projection(ref data) => data.has_type_flags(flags),
|
||||
ty::Predicate::WellFormed(data) => data.has_type_flags(flags),
|
||||
ty::Predicate::ObjectSafe(_trait_def_id) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::TraitPredicate<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.trait_ref.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::EquatePredicate<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.0.has_type_flags(flags) || self.1.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl HasTypeFlags for ty::Region {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
if flags.intersects(TypeFlags::HAS_LOCAL_NAMES) {
|
||||
// does this represent a region that cannot be named in a global
|
||||
// way? used in fulfillment caching.
|
||||
match *self {
|
||||
ty::ReStatic | ty::ReEmpty => {}
|
||||
_ => return true
|
||||
}
|
||||
}
|
||||
if flags.intersects(TypeFlags::HAS_RE_INFER) {
|
||||
match *self {
|
||||
ty::ReVar(_) | ty::ReSkolemized(..) => { return true }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<T:HasTypeFlags,U:HasTypeFlags> HasTypeFlags for ty::OutlivesPredicate<T,U> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.0.has_type_flags(flags) || self.1.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::ProjectionPredicate<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.projection_ty.has_type_flags(flags) || self.ty.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::ProjectionTy<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.trait_ref.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for Ty<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.flags.get().intersects(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for TypeAndMut<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.ty.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for TraitRef<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.substs.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for subst::Substs<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.types.has_type_flags(flags) || match self.regions {
|
||||
subst::ErasedRegions => false,
|
||||
subst::NonerasedRegions(ref r) => r.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,T> HasTypeFlags for Option<T>
|
||||
where T : HasTypeFlags
|
||||
{
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.iter().any(|t| t.has_type_flags(flags))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,T> HasTypeFlags for Rc<T>
|
||||
where T : HasTypeFlags
|
||||
{
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
(**self).has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,T> HasTypeFlags for Box<T>
|
||||
where T : HasTypeFlags
|
||||
{
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
(**self).has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> HasTypeFlags for ty::Binder<T>
|
||||
where T : HasTypeFlags
|
||||
{
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.0.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::FnOutput<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
match *self {
|
||||
ty::FnConverging(t) => t.has_type_flags(flags),
|
||||
ty::FnDiverging => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::FnSig<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.inputs.iter().any(|t| t.has_type_flags(flags)) ||
|
||||
self.output.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::BareFnTy<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.sig.has_type_flags(flags)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> HasTypeFlags for ty::ClosureSubsts<'tcx> {
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.func_substs.has_type_flags(flags) ||
|
||||
self.upvar_tys.iter().any(|t| t.has_type_flags(flags))
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Lift implementations
|
||||
|
||||
|
|
@ -511,6 +127,10 @@ macro_rules! CopyImpls {
|
|||
fn fold_with<F:TypeFolder<'tcx>>(&self, _: &mut F) -> $ty {
|
||||
*self
|
||||
}
|
||||
|
||||
fn visit_with<F: TypeVisitor<'tcx>>(&self, _: &mut F) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
|
|
@ -522,18 +142,30 @@ impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T
|
|||
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> (T, U) {
|
||||
(self.0.fold_with(folder), self.1.fold_with(folder))
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.0.visit_with(visitor) || self.1.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Option<T> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Option<T> {
|
||||
self.as_ref().map(|t| t.fold_with(folder))
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.iter().any(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Rc<T> {
|
||||
Rc::new((**self).fold_with(folder))
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
|
||||
|
|
@ -541,24 +173,50 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
|
|||
let content: T = (**self).fold_with(folder);
|
||||
box content
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
(**self).visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Vec<T> {
|
||||
self.iter().map(|t| t.fold_with(folder)).collect()
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.iter().any(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
|
||||
folder.fold_binder(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
folder.enter_region_binder();
|
||||
let result = ty::Binder(self.0.fold_with(folder));
|
||||
folder.exit_region_binder();
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
visitor.enter_region_binder();
|
||||
if self.0.visit_with(visitor) { return true }
|
||||
visitor.exit_region_binder();
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for P<[T]> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> P<[T]> {
|
||||
self.iter().map(|t| t.fold_with(folder)).collect()
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.iter().any(|t| t.visit_with(visitor))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace<T> {
|
||||
|
|
@ -582,60 +240,244 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace<T> {
|
|||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
let mut entered_region_binder = false;
|
||||
let result = self.iter_enumerated().any(|(space, index, t)| {
|
||||
if space == subst::FnSpace && index == 0 {
|
||||
visitor.enter_region_binder();
|
||||
entered_region_binder = true;
|
||||
}
|
||||
t.visit_with(visitor)
|
||||
});
|
||||
if entered_region_binder {
|
||||
visitor.exit_region_binder();
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::TraitTy<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::TraitTy {
|
||||
principal: self.principal.fold_with(folder),
|
||||
bounds: self.bounds.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.principal.visit_with(visitor) || self.bounds.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Ty<'tcx> {
|
||||
folder.fold_ty(*self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let sty = match self.sty {
|
||||
ty::TyBox(typ) => ty::TyBox(typ.fold_with(folder)),
|
||||
ty::TyRawPtr(ref tm) => ty::TyRawPtr(tm.fold_with(folder)),
|
||||
ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz),
|
||||
ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)),
|
||||
ty::TyEnum(tid, ref substs) => {
|
||||
let substs = substs.fold_with(folder);
|
||||
ty::TyEnum(tid, folder.tcx().mk_substs(substs))
|
||||
}
|
||||
ty::TyTrait(ref trait_ty) => ty::TyTrait(trait_ty.fold_with(folder)),
|
||||
ty::TyTuple(ref ts) => ty::TyTuple(ts.fold_with(folder)),
|
||||
ty::TyBareFn(opt_def_id, ref f) => {
|
||||
let bfn = f.fold_with(folder);
|
||||
ty::TyBareFn(opt_def_id, folder.tcx().mk_bare_fn(bfn))
|
||||
}
|
||||
ty::TyRef(r, ref tm) => {
|
||||
let r = r.fold_with(folder);
|
||||
ty::TyRef(folder.tcx().mk_region(r), tm.fold_with(folder))
|
||||
}
|
||||
ty::TyStruct(did, ref substs) => {
|
||||
let substs = substs.fold_with(folder);
|
||||
ty::TyStruct(did, folder.tcx().mk_substs(substs))
|
||||
}
|
||||
ty::TyClosure(did, ref substs) => {
|
||||
ty::TyClosure(did, substs.fold_with(folder))
|
||||
}
|
||||
ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)),
|
||||
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
|
||||
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
|
||||
ty::TyParam(..) => self.sty.clone(),
|
||||
};
|
||||
folder.tcx().mk_ty(sty)
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
visitor.visit_ty(self)
|
||||
}
|
||||
|
||||
fn visit_subitems_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match self.sty {
|
||||
ty::TyBox(typ) => typ.visit_with(visitor),
|
||||
ty::TyRawPtr(ref tm) => tm.visit_with(visitor),
|
||||
ty::TyArray(typ, _sz) => typ.visit_with(visitor),
|
||||
ty::TySlice(typ) => typ.visit_with(visitor),
|
||||
ty::TyEnum(_tid, ref substs) => substs.visit_with(visitor),
|
||||
ty::TyTrait(ref trait_ty) => trait_ty.visit_with(visitor),
|
||||
ty::TyTuple(ref ts) => ts.visit_with(visitor),
|
||||
ty::TyBareFn(_opt_def_id, ref f) => f.visit_with(visitor),
|
||||
ty::TyRef(r, ref tm) => r.visit_with(visitor) || tm.visit_with(visitor),
|
||||
ty::TyStruct(_did, ref substs) => substs.visit_with(visitor),
|
||||
ty::TyClosure(_did, ref substs) => substs.visit_with(visitor),
|
||||
ty::TyProjection(ref data) => data.visit_with(visitor),
|
||||
ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) |
|
||||
ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) |
|
||||
ty::TyParam(..) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::BareFnTy<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::BareFnTy<'tcx> {
|
||||
folder.fold_bare_fn_ty(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::BareFnTy { sig: self.sig.fold_with(folder),
|
||||
abi: self.abi,
|
||||
unsafety: self.unsafety }
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.sig.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ClosureTy<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureTy<'tcx> {
|
||||
folder.fold_closure_ty(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::ClosureTy {
|
||||
sig: self.sig.fold_with(folder),
|
||||
unsafety: self.unsafety,
|
||||
abi: self.abi,
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.sig.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::TypeAndMut<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeAndMut<'tcx> {
|
||||
folder.fold_mt(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::TypeAndMut { ty: self.ty.fold_with(folder), mutbl: self.mutbl }
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.ty.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::FnOutput<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnOutput<'tcx> {
|
||||
folder.fold_output(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
match *self {
|
||||
ty::FnConverging(ref ty) => ty::FnConverging(ty.fold_with(folder)),
|
||||
ty::FnDiverging => ty::FnDiverging
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match *self {
|
||||
ty::FnConverging(ref ty) => ty.visit_with(visitor),
|
||||
ty::FnDiverging => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig<'tcx> {
|
||||
folder.fold_fn_sig(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::FnSig { inputs: self.inputs.fold_with(folder),
|
||||
output: self.output.fold_with(folder),
|
||||
variadic: self.variadic }
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.inputs.visit_with(visitor) || self.output.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitRef<'tcx> {
|
||||
folder.fold_trait_ref(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let substs = self.substs.fold_with(folder);
|
||||
ty::TraitRef {
|
||||
def_id: self.def_id,
|
||||
substs: folder.tcx().mk_substs(substs),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.substs.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::Region {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Region {
|
||||
folder.fold_region(*self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> Self {
|
||||
*self
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
visitor.visit_region(*self)
|
||||
}
|
||||
|
||||
fn visit_subitems_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for subst::Substs<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> subst::Substs<'tcx> {
|
||||
folder.fold_substs(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
let regions = match self.regions {
|
||||
subst::ErasedRegions => subst::ErasedRegions,
|
||||
subst::NonerasedRegions(ref regions) => {
|
||||
subst::NonerasedRegions(regions.fold_with(folder))
|
||||
}
|
||||
};
|
||||
|
||||
subst::Substs { regions: regions,
|
||||
types: self.types.fold_with(folder) }
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.types.visit_with(visitor) || match self.regions {
|
||||
subst::ErasedRegions => false,
|
||||
subst::NonerasedRegions(ref regions) => regions.visit_with(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
|
||||
|
|
@ -646,6 +488,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ClosureSubsts<'tcx> {
|
|||
upvar_tys: self.upvar_tys.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.func_substs.visit_with(visitor) || self.upvar_tys.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> {
|
||||
|
|
@ -654,24 +500,61 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> {
|
|||
substs: self.substs.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.substs.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoRef<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::adjustment::AutoRef<'tcx> {
|
||||
folder.fold_autoref(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
match *self {
|
||||
ty::adjustment::AutoPtr(r, m) => {
|
||||
let r = r.fold_with(folder);
|
||||
ty::adjustment::AutoPtr(folder.tcx().mk_region(r), m)
|
||||
}
|
||||
ty::adjustment::AutoUnsafe(m) => ty::adjustment::AutoUnsafe(m)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match *self {
|
||||
ty::adjustment::AutoPtr(r, _m) => r.visit_with(visitor),
|
||||
ty::adjustment::AutoUnsafe(_m) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> ty::BuiltinBounds {
|
||||
*self
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
|
||||
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds<'tcx> {
|
||||
folder.fold_existential_bounds(self)
|
||||
}
|
||||
|
||||
fn fold_subitems_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::ExistentialBounds {
|
||||
region_bound: self.region_bound.fold_with(folder),
|
||||
builtin_bounds: self.builtin_bounds,
|
||||
projection_bounds: self.projection_bounds.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.region_bound.visit_with(visitor) || self.projection_bounds.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
|
||||
|
|
@ -686,6 +569,11 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
|
|||
object_lifetime_default: self.object_lifetime_default.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.default.visit_with(visitor) ||
|
||||
self.object_lifetime_default.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault {
|
||||
|
|
@ -701,6 +589,13 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ObjectLifetimeDefault {
|
|||
ty::ObjectLifetimeDefault::Specific(r.fold_with(folder)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match *self {
|
||||
ty::ObjectLifetimeDefault::Specific(r) => r.visit_with(visitor),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef {
|
||||
|
|
@ -713,6 +608,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef {
|
|||
bounds: self.bounds.fold_with(folder)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.bounds.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> {
|
||||
|
|
@ -722,6 +621,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> {
|
|||
regions: self.regions.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.types.visit_with(visitor) || self.regions.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
|
||||
|
|
@ -730,6 +633,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> {
|
|||
predicates: self.predicates.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.predicates.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
|
||||
|
|
@ -751,6 +658,18 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
|
|||
ty::Predicate::ObjectSafe(trait_def_id),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
match *self {
|
||||
ty::Predicate::Trait(ref a) => a.visit_with(visitor),
|
||||
ty::Predicate::Equate(ref binder) => binder.visit_with(visitor),
|
||||
ty::Predicate::RegionOutlives(ref binder) => binder.visit_with(visitor),
|
||||
ty::Predicate::TypeOutlives(ref binder) => binder.visit_with(visitor),
|
||||
ty::Predicate::Projection(ref binder) => binder.visit_with(visitor),
|
||||
ty::Predicate::WellFormed(data) => data.visit_with(visitor),
|
||||
ty::Predicate::ObjectSafe(_trait_def_id) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
|
||||
|
|
@ -760,6 +679,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
|
|||
ty: self.ty.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.projection_ty.visit_with(visitor) || self.ty.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
|
||||
|
|
@ -769,6 +692,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
|
|||
item_name: self.item_name,
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.trait_ref.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> {
|
||||
|
|
@ -777,6 +704,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::InstantiatedPredicates<'tcx> {
|
|||
predicates: self.predicates.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.predicates.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
|
||||
|
|
@ -784,6 +715,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
|
|||
ty::EquatePredicate(self.0.fold_with(folder),
|
||||
self.1.fold_with(folder))
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.0.visit_with(visitor) || self.1.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
|
||||
|
|
@ -792,6 +727,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
|
|||
trait_ref: self.trait_ref.fold_with(folder)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.trait_ref.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
|
||||
|
|
@ -802,6 +741,10 @@ impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
|
|||
ty::OutlivesPredicate(self.0.fold_with(folder),
|
||||
self.1.fold_with(folder))
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.0.visit_with(visitor) || self.1.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> {
|
||||
|
|
@ -812,6 +755,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> {
|
|||
ty: self.ty.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.ty.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where 'tcx: 'a {
|
||||
|
|
@ -826,4 +773,23 @@ impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where '
|
|||
free_id_outlive: self.free_id_outlive,
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.free_substs.visit_with(visitor) ||
|
||||
self.implicit_region_bound.visit_with(visitor) ||
|
||||
self.caller_bounds.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for ty::TypeScheme<'tcx> {
|
||||
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
|
||||
ty::TypeScheme {
|
||||
generics: self.generics.fold_with(folder),
|
||||
ty: self.ty.fold_with(folder),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.generics.visit_with(visitor) || self.ty.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -256,6 +256,10 @@ impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
|
|||
-> TraitAndProjections<'tcx> {
|
||||
TraitAndProjections(self.0.fold_with(folder), self.1.fold_with(folder))
|
||||
}
|
||||
|
||||
fn visit_with<V: ty::fold::TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
|
||||
self.0.visit_with(visitor) || self.1.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for TraitAndProjections<'tcx> {
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn monomorphize<T>(&self, value: &T) -> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
monomorphize::apply_param_substs(self.ccx.tcx(),
|
||||
self.param_substs,
|
||||
|
|
@ -650,7 +650,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn monomorphize<T>(&self, value: &T) -> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
monomorphize::apply_param_substs(self.tcx(),
|
||||
self.fcx.param_substs,
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>,
|
|||
param_substs: &Substs<'tcx>,
|
||||
value: &T)
|
||||
-> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
let substituted = value.subst(tcx, param_substs);
|
||||
normalize_associated_type(tcx, &substituted)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
use middle::infer::InferCtxt;
|
||||
use middle::traits::{self, FulfillmentContext, Normalized, MiscObligation,
|
||||
SelectionContext, ObligationCause};
|
||||
use middle::ty::HasTypeFlags;
|
||||
use middle::ty::fold::TypeFoldable;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
|
|
@ -23,7 +22,7 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
|
|||
body_id: ast::NodeId,
|
||||
value: &T)
|
||||
-> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
debug!("normalize_associated_types_in(value={:?})", value);
|
||||
let mut selcx = SelectionContext::new(infcx);
|
||||
|
|
|
|||
|
|
@ -318,7 +318,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
|
|||
body_id: ast::NodeId,
|
||||
value: &T)
|
||||
-> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
let mut fulfillment_cx = self.infcx.fulfillment_cx.borrow_mut();
|
||||
assoc::normalize_associated_types_in(&self.infcx,
|
||||
|
|
@ -1334,7 +1334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
substs: &Substs<'tcx>,
|
||||
value: &T)
|
||||
-> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
let value = value.subst(self.tcx(), substs);
|
||||
let result = self.normalize_associated_types_in(span, &value);
|
||||
|
|
@ -1360,7 +1360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
|
||||
|
||||
fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
|
||||
where T : TypeFoldable<'tcx> + HasTypeFlags
|
||||
where T : TypeFoldable<'tcx>
|
||||
{
|
||||
self.inh.normalize_associated_types_in(span, self.body_id, value)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue