Auto merge of #98206 - eggyal:align-to-chalk-folding-api, r=jackh726

Split TypeVisitable from TypeFoldable

Impl of rust-lang/compiler-team#520 following MCP approval.

r? `@ghost`
This commit is contained in:
bors 2022-07-06 05:48:11 +00:00
commit 5b8cf49c51
171 changed files with 1481 additions and 1306 deletions

View File

@ -5,8 +5,8 @@ use rustc_middle::mir::{
BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue,
SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection,
};
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{self, RegionVid, Ty};
use crate::{
@ -163,7 +163,7 @@ impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
/// `location`.
fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location)
where
T: TypeFoldable<'tcx>,
T: TypeVisitable<'tcx>,
{
debug!("add_regular_live_constraint(live_ty={:?}, location={:?})", live_ty, location);

View File

@ -19,7 +19,9 @@ use rustc_middle::mir::{
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode;
use rustc_middle::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{
self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable,
};
use rustc_span::Span;
use crate::{

View File

@ -2,7 +2,9 @@ use rustc_data_structures::vec_map::VecMap;
use rustc_hir::def_id::DefId;
use rustc_hir::OpaqueTyOrigin;
use rustc_infer::infer::InferCtxt;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable};
use rustc_middle::ty::{
self, OpaqueHiddenType, OpaqueTypeKey, TyCtxt, TypeFoldable, TypeVisitable,
};
use rustc_trait_selection::opaque_types::InferCtxtExt;
use super::RegionInferenceContext;

View File

@ -6,7 +6,7 @@ use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::TypeVisitable;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::{Span, DUMMY_SP};

View File

@ -3,7 +3,7 @@ use rustc_index::bit_set::HybridBitSet;
use rustc_index::interval::IntervalSet;
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
use rustc_middle::ty::{Ty, TypeFoldable};
use rustc_middle::ty::{Ty, TypeVisitable};
use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@ -477,7 +477,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
/// points `live_at`.
fn add_use_live_facts_for(
&mut self,
value: impl TypeFoldable<'tcx>,
value: impl TypeVisitable<'tcx>,
live_at: &IntervalSet<PointIndex>,
) {
debug!("add_use_live_facts_for(value={:?})", value);
@ -542,7 +542,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
fn make_all_regions_live(
elements: &RegionValueElements,
typeck: &mut TypeChecker<'_, 'tcx>,
value: impl TypeFoldable<'tcx>,
value: impl TypeVisitable<'tcx>,
live_at: &IntervalSet<PointIndex>,
) {
debug!("make_all_regions_live(value={:?})", value);

View File

@ -27,8 +27,8 @@ use rustc_middle::mir::AssertKind;
use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueHiddenType,
OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,

View File

@ -79,7 +79,7 @@ mod prelude {
pub(crate) use rustc_middle::ty::layout::{self, LayoutOf, TyAndLayout};
pub(crate) use rustc_middle::ty::{
self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
TypeFoldable, UintTy,
TypeFoldable, TypeVisitable, UintTy,
};
pub(crate) use rustc_target::abi::{Abi, Scalar, Size, VariantIdx};

View File

@ -1,6 +1,6 @@
use gccjit::{FunctionType, RValue};
use rustc_codegen_ssa::traits::BaseTypeMethods;
use rustc_middle::ty::{self, Instance, TypeFoldable};
use rustc_middle::ty::{self, Instance, TypeVisitable};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use crate::abi::FnAbiGccExt;

View File

@ -1,7 +1,7 @@
use rustc_codegen_ssa::traits::PreDefineMethods;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty::{self, Instance, TypeFoldable};
use rustc_middle::ty::{self, Instance, TypeVisitable};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
use rustc_span::def_id::DefId;

View File

@ -3,7 +3,7 @@ use std::fmt::Write;
use gccjit::{Struct, Type};
use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
use rustc_middle::bug;
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_middle::ty::{self, Ty, TypeVisitable};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_target::abi::{self, Abi, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};

View File

@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*;
use tracing::debug;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
use rustc_middle::ty::{self, Instance, TypeFoldable};
use rustc_middle::ty::{self, Instance, TypeVisitable};
/// Codegens a reference to a fn/method item, monomorphizing and
/// inlining as it goes.

View File

@ -27,7 +27,7 @@ use rustc_index::vec::IndexVec;
use rustc_middle::mir;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitable};
use rustc_session::config::{self, DebugInfo};
use rustc_session::Session;
use rustc_span::symbol::Symbol;

View File

@ -8,7 +8,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE};
pub use rustc_middle::mir::mono::MonoItem;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeFoldable};
use rustc_middle::ty::{self, Instance, TypeVisitable};
use rustc_session::config::CrateType;
use rustc_target::spec::RelocModel;
use tracing::debug;

View File

@ -6,7 +6,7 @@ use rustc_codegen_ssa::traits::*;
use rustc_middle::bug;
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Ty, TypeFoldable};
use rustc_middle::ty::{self, Ty, TypeVisitable};
use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
use rustc_target::abi::{Int, Pointer, F32, F64};
use rustc_target::abi::{PointeeInfo, Scalar, Size, TyAbiInterface, Variants};

View File

@ -17,7 +17,7 @@ use rustc_middle::mir::AssertKind;
use rustc_middle::mir::{self, SwitchTargets};
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
use rustc_middle::ty::{self, Instance, Ty, TypeVisitable};
use rustc_span::source_map::Span;
use rustc_span::{sym, Symbol};
use rustc_symbol_mangling::typeid_for_fnabi;

View File

@ -2,7 +2,7 @@ use crate::traits::*;
use rustc_middle::mir;
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable, TypeVisitable};
use rustc_symbol_mangling::typeid_for_fnabi;
use rustc_target::abi::call::{FnAbi, PassMode};

View File

@ -1,5 +1,5 @@
use rustc_middle::mir::interpret::InterpResult;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use std::convert::TryInto;
use std::ops::ControlFlow;
@ -10,7 +10,7 @@ use std::ops::ControlFlow;
/// case these parameters are unused.
pub(crate) fn ensure_monomorphic_enough<'tcx, T>(tcx: TyCtxt<'tcx>, ty: T) -> InterpResult<'tcx>
where
T: TypeFoldable<'tcx>,
T: TypeVisitable<'tcx>,
{
debug!("ensure_monomorphic_enough: ty={:?}", ty);
if !ty.needs_subst() {

View File

@ -10,7 +10,7 @@ use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceC
use rustc_middle::mir::*;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::{self, adjustment::PointerCast, Instance, InstanceDef, Ty, TyCtxt};
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeFoldable};
use rustc_middle::ty::{Binder, TraitPredicate, TraitRef, TypeVisitable};
use rustc_mir_dataflow::{self, Analysis};
use rustc_span::{sym, Span, Symbol};
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;

View File

@ -17,7 +17,7 @@ use rustc_middle::mir::traversal::ReversePostorderIter;
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, List, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, List, TyCtxt, TypeVisitable};
use rustc_span::Span;
use rustc_index::vec::{Idx, IndexVec};

View File

@ -12,7 +12,7 @@ use rustc_middle::mir::{
Statement, StatementKind, Terminator, TerminatorKind, UnOp, START_BLOCK,
};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_mir_dataflow::impls::MaybeStorageLive;
use rustc_mir_dataflow::storage::always_live_locals;
use rustc_mir_dataflow::{Analysis, ResultsCursor};

View File

@ -37,7 +37,7 @@ use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitable};
use rustc_middle::ty::{IntType, UintType};
use rustc_span::{Span, DUMMY_SP};

View File

@ -68,7 +68,7 @@ use rustc_middle::dep_graph::DepContext;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable,
TypeSuperFoldable,
TypeSuperVisitable, TypeVisitable,
};
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
@ -1540,7 +1540,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
impl<'tcx> ty::visit::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
let span = self.tcx.def_span(def_id);

View File

@ -10,7 +10,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::{walk_ty, Visitor};
use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind};
use rustc_middle::ty::{
self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperFoldable, TypeVisitor,
self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
};
use rustc_span::symbol::Ident;
use rustc_span::Span;

View File

@ -11,7 +11,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::Visitor;
use rustc_middle::hir::nested_filter;
use rustc_middle::ty::print::RegionHighlightMode;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperFoldable, TypeVisitor};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_span::{Span, Symbol};
use std::ops::ControlFlow;
@ -88,7 +88,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
}
}
impl<'tcx> ty::fold::TypeVisitor<'tcx> for HighlightBuilder<'tcx> {
impl<'tcx> ty::visit::TypeVisitor<'tcx> for HighlightBuilder<'tcx> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if !r.has_name() && self.counter <= 3 {
self.highlight.highlighting_region(r, self.counter);

View File

@ -5,7 +5,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
use crate::infer::TyCtxt;
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeFoldable};
use rustc_middle::ty::{self, Binder, DefIdTree, Region, Ty, TypeVisitable};
use rustc_span::Span;
/// Information about the anonymous region we are searching for.
@ -142,7 +142,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
fn includes_region(
&self,
ty: Binder<'tcx, impl TypeFoldable<'tcx>>,
ty: Binder<'tcx, impl TypeVisitable<'tcx>>,
region: ty::BoundRegionKind,
) -> bool {
let late_bound_regions = self.tcx().collect_referenced_late_bound_regions(&ty);

View File

@ -34,7 +34,7 @@ use super::InferCtxt;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::infer::unify_key::ToType;
use rustc_middle::ty::fold::TypeFolder;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable};
use std::collections::hash_map::Entry;
pub struct TypeFreshener<'a, 'tcx> {

View File

@ -25,6 +25,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef};
use rustc_middle::ty::visit::TypeVisitable;
pub use rustc_middle::ty::IntVarValue;
use rustc_middle::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt};
use rustc_middle::ty::{ConstVid, FloatVid, IntVid, TyVid};
@ -318,7 +319,7 @@ pub struct InferCtxt<'a, 'tcx> {
}
/// See the `error_reporting` module for more details.
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
pub enum ValuePairs<'tcx> {
Regions(ExpectedFound<ty::Region<'tcx>>),
Terms(ExpectedFound<ty::Term<'tcx>>),
@ -1438,7 +1439,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
/// `resolve_vars_if_possible()`.
pub fn unresolved_type_vars<T>(&self, value: &T) -> Option<(Ty<'tcx>, Option<Span>)>
where
T: TypeFoldable<'tcx>,
T: TypeVisitable<'tcx>,
{
value.visit_with(&mut resolve::UnresolvedTypeFinder::new(self)).break_value()
}

View File

@ -27,8 +27,8 @@ use crate::infer::{ConstVarValue, ConstVariableValue};
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::fold::{TypeFoldable, TypeSuperFoldable, TypeVisitor};
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
use rustc_span::Span;
use std::fmt::Debug;
@ -810,7 +810,7 @@ struct ScopeInstantiator<'me, 'tcx> {
}
impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
fn visit_binder<T: TypeFoldable<'tcx>>(
fn visit_binder<T: TypeVisitable<'tcx>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {

View File

@ -9,7 +9,8 @@ use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::subst::{GenericArgKind, Subst};
use rustc_middle::ty::{
self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor,
self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitor,
};
use rustc_span::Span;
@ -461,7 +462,7 @@ impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP>
where
OP: FnMut(ty::Region<'tcx>),
{
fn visit_binder<T: TypeFoldable<'tcx>>(
fn visit_binder<T: TypeVisitable<'tcx>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {

View File

@ -4,7 +4,7 @@
use rustc_data_structures::sso::SsoHashSet;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
use smallvec::{smallvec, SmallVec};
#[derive(Debug)]

View File

@ -69,7 +69,7 @@ use crate::infer::{
use crate::traits::{ObligationCause, ObligationCauseCode};
use rustc_data_structures::undo_log::UndoLogs;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, Region, Ty, TyCtxt, TypeVisitable};
use smallvec::smallvec;
impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {

View File

@ -1,7 +1,7 @@
use std::collections::hash_map::Entry;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::TypeVisitable;
use rustc_middle::ty::{
self,
error::TypeError,

View File

@ -165,7 +165,7 @@ pub struct Verify<'tcx> {
pub bound: VerifyBound<'tcx>,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
pub enum GenericKind<'tcx> {
Param(ty::ParamTy),
Projection(ty::ProjectionTy<'tcx>),
@ -272,7 +272,7 @@ pub enum VerifyBound<'tcx> {
/// }
/// }
/// ```
#[derive(Debug, Copy, Clone, TypeFoldable)]
#[derive(Debug, Copy, Clone, TypeFoldable, TypeVisitable)]
pub struct VerifyIfEq<'tcx> {
/// Type which must match the generic `G`
pub ty: Ty<'tcx>,

View File

@ -1,8 +1,9 @@
use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use super::{FixupError, FixupResult, InferCtxt, Span};
use rustc_middle::mir;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable, TypeVisitor};
use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitor};
use rustc_middle::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable, TypeVisitable};
use std::ops::ControlFlow;

View File

@ -4,8 +4,8 @@ use super::SubregionOrigin;
use crate::infer::combine::ConstEquateRelation;
use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
use crate::traits::Obligation;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::TyVar;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt};
use std::mem;

View File

@ -20,7 +20,7 @@ pub struct MismatchedProjectionTypes<'tcx> {
pub err: ty::error::TypeError<'tcx>,
}
#[derive(Clone, TypeFoldable)]
#[derive(Clone, TypeFoldable, TypeVisitable)]
pub struct Normalized<'tcx, T> {
pub value: T,
pub obligations: Vec<PredicateObligation<'tcx>>,

View File

@ -1,7 +1,8 @@
use crate::traits;
use crate::traits::project::Normalized;
use rustc_middle::ty;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeVisitor};
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable};
use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor};
use std::fmt;
use std::ops::ControlFlow;
@ -68,7 +69,9 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx
param_env: self.param_env.try_fold_with(folder)?,
})
}
}
impl<'tcx, O: TypeVisitable<'tcx>> TypeVisitable<'tcx> for traits::Obligation<'tcx, O> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.predicate.visit_with(visitor)?;
self.param_env.visit_with(visitor)

View File

@ -1645,7 +1645,7 @@ declare_lint_pass!(
impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::PredicateKind::*;
if cx.tcx.features().trivial_bounds {

View File

@ -1,7 +1,7 @@
use crate::{context::LintContext, LateContext, LateLintPass};
use rustc_errors::fluent;
use rustc_hir as hir;
use rustc_middle::ty::{fold::TypeFoldable, Ty};
use rustc_middle::ty::{visit::TypeVisitable, Ty};
use rustc_span::{symbol::sym, Span};
declare_lint! {

View File

@ -1,5 +1,5 @@
use crate::context::LintContext;
use crate::rustc_middle::ty::TypeFoldable;
use crate::rustc_middle::ty::TypeVisitable;
use crate::LateContext;
use crate::LateLintPass;
use rustc_errors::fluent;

View File

@ -7,7 +7,7 @@ use rustc_hir as hir;
use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol, DUMMY_SP};
@ -1182,7 +1182,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
}
impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
impl<'a, 'tcx> ty::visit::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
type BreakTy = Ty<'tcx>;
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {

View File

@ -18,6 +18,7 @@ mod query;
mod serialize;
mod symbols;
mod type_foldable;
mod type_visitable;
#[proc_macro]
pub fn rustc_queries(input: TokenStream) -> TokenStream {
@ -121,6 +122,7 @@ decl_derive!([TyEncodable] => serialize::type_encodable_derive);
decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive);
decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive);
decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
decl_derive!([TypeVisitable, attributes(type_visitable)] => type_visitable::type_visitable_derive);
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
decl_derive!(
[SessionDiagnostic, attributes(

View File

@ -11,11 +11,6 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
}
s.add_bounds(synstructure::AddBounds::Generics);
let body_visit = s.each(|bind| {
quote! {
::rustc_middle::ty::fold::TypeFoldable::visit_with(#bind, __folder)?;
}
});
s.bind_with(|_| synstructure::BindStyle::Move);
let body_fold = s.each_variant(|vi| {
let bindings = vi.bindings();
@ -36,14 +31,6 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
) -> Result<Self, __F::Error> {
Ok(match self { #body_fold })
}
fn visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>(
&self,
__folder: &mut __F
) -> ::std::ops::ControlFlow<__F::BreakTy> {
match *self { #body_visit }
::std::ops::ControlFlow::CONTINUE
}
},
)
}

View File

@ -0,0 +1,33 @@
use quote::quote;
use syn::parse_quote;
pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
panic!("cannot derive on union")
}
if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
s.add_impl_generic(parse_quote! { 'tcx });
}
s.add_bounds(synstructure::AddBounds::Generics);
let body_visit = s.each(|bind| {
quote! {
::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?;
}
});
s.bind_with(|_| synstructure::BindStyle::Move);
s.bound_impl(
quote!(::rustc_middle::ty::visit::TypeVisitable<'tcx>),
quote! {
fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<'tcx>>(
&self,
__visitor: &mut __V
) -> ::std::ops::ControlFlow<__V::BreakTy> {
match *self { #body_visit }
::std::ops::ControlFlow::CONTINUE
}
},
)
}

View File

@ -4,18 +4,8 @@ use crate::ty::Ty;
use rustc_hir::HirId;
use rustc_target::abi::VariantIdx;
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
TypeFoldable,
HashStable
)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum PlaceBase {
/// A temporary variable.
Rvalue,
@ -27,18 +17,8 @@ pub enum PlaceBase {
Upvar(ty::UpvarId),
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
TypeFoldable,
HashStable
)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum ProjectionKind {
/// A dereference of a pointer, reference or `Box<T>` of the given type.
Deref,
@ -58,18 +38,8 @@ pub enum ProjectionKind {
Subslice,
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
TypeFoldable,
HashStable
)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct Projection<'tcx> {
/// Type after the projection is applied.
pub ty: Ty<'tcx>,
@ -81,7 +51,8 @@ pub struct Projection<'tcx> {
/// A `Place` represents how a value is located in memory.
///
/// This is an HIR version of [`rustc_middle::mir::Place`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct Place<'tcx> {
/// The type of the `PlaceBase`
pub base_ty: Ty<'tcx>,
@ -94,7 +65,8 @@ pub struct Place<'tcx> {
/// A `PlaceWithHirId` represents how a value is located in memory.
///
/// This is an HIR version of [`rustc_middle::mir::Place`].
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct PlaceWithHirId<'tcx> {
/// `HirId` of the expression or pattern producing this value.
pub hir_id: HirId,

View File

@ -34,7 +34,7 @@ use std::ops::Index;
/// variables have been rewritten to "canonical vars". These are
/// numbered starting from 0 in order of first appearance.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
#[derive(HashStable, TypeFoldable, Lift)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct Canonical<'tcx, V> {
pub max_universe: ty::UniverseIndex,
pub variables: CanonicalVarInfos<'tcx>,
@ -53,7 +53,7 @@ pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
/// variables. You will need to supply it later to instantiate the
/// canonicalized query response.
#[derive(Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
#[derive(HashStable, TypeFoldable, Lift)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct CanonicalVarValues<'tcx> {
pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>,
}
@ -173,7 +173,7 @@ pub enum CanonicalTyVarKind {
/// After we execute a query with a canonicalized key, we get back a
/// `Canonical<QueryResponse<..>>`. You can use
/// `instantiate_query_result` to access the data in this result.
#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct QueryResponse<'tcx, R> {
pub var_values: CanonicalVarValues<'tcx>,
pub region_constraints: QueryRegionConstraints<'tcx>,
@ -187,7 +187,7 @@ pub struct QueryResponse<'tcx, R> {
pub value: R,
}
#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct QueryRegionConstraints<'tcx> {
pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
pub member_constraints: Vec<MemberConstraint<'tcx>>,
@ -293,7 +293,7 @@ impl<'tcx, V> Canonical<'tcx, V> {
pub type QueryOutlivesConstraint<'tcx> =
ty::Binder<'tcx, ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>;
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
for <'tcx> {
crate::infer::canonical::Certainty,
crate::infer::canonical::CanonicalVarInfo<'tcx>,
@ -301,7 +301,7 @@ TrivialTypeFoldableAndLiftImpls! {
}
}
TrivialTypeFoldableImpls! {
TrivialTypeTraversalImpls! {
for <'tcx> {
crate::infer::canonical::CanonicalVarInfos<'tcx>,
}

View File

@ -13,7 +13,7 @@ use rustc_span::Span;
/// ```text
/// R0 member of [O1..On]
/// ```
#[derive(Debug, Clone, HashStable, TypeFoldable, Lift)]
#[derive(Debug, Clone, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct MemberConstraint<'tcx> {
/// The `DefId` of the opaque type causing this constraint: used for error reporting.
pub opaque_type_def_id: DefId,

View File

@ -18,7 +18,7 @@ macro_rules! span_bug {
}
///////////////////////////////////////////////////////////////////////////
// Lift and TypeFoldable macros
// Lift and TypeFoldable/TypeVisitable macros
//
// When possible, use one of these (relatively) convenient macros to write
// the impls for you.
@ -48,7 +48,7 @@ macro_rules! CloneLiftImpls {
/// Used for types that are `Copy` and which **do not care arena
/// allocated data** (i.e., don't need to be folded).
#[macro_export]
macro_rules! TrivialTypeFoldableImpls {
macro_rules! TrivialTypeTraversalImpls {
(for <$tcx:lifetime> { $($ty:ty,)+ }) => {
$(
impl<$tcx> $crate::ty::fold::TypeFoldable<$tcx> for $ty {
@ -58,8 +58,10 @@ macro_rules! TrivialTypeFoldableImpls {
) -> ::std::result::Result<$ty, F::Error> {
Ok(self)
}
}
fn visit_with<F: $crate::ty::fold::TypeVisitor<$tcx>>(
impl<$tcx> $crate::ty::visit::TypeVisitable<$tcx> for $ty {
fn visit_with<F: $crate::ty::visit::TypeVisitor<$tcx>>(
&self,
_: &mut F)
-> ::std::ops::ControlFlow<F::BreakTy>
@ -71,7 +73,7 @@ macro_rules! TrivialTypeFoldableImpls {
};
($($ty:ty,)+) => {
TrivialTypeFoldableImpls! {
TrivialTypeTraversalImpls! {
for <'tcx> {
$($ty,)+
}
@ -80,15 +82,15 @@ macro_rules! TrivialTypeFoldableImpls {
}
#[macro_export]
macro_rules! TrivialTypeFoldableAndLiftImpls {
macro_rules! TrivialTypeTraversalAndLiftImpls {
($($t:tt)*) => {
TrivialTypeFoldableImpls! { $($t)* }
TrivialTypeTraversalImpls! { $($t)* }
CloneLiftImpls! { $($t)* }
}
}
#[macro_export]
macro_rules! EnumTypeFoldableImpl {
macro_rules! EnumTypeTraversalImpl {
(impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path {
$($variants:tt)*
} $(where $($wc:tt)*)*) => {
@ -99,14 +101,22 @@ macro_rules! EnumTypeFoldableImpl {
self,
folder: &mut V,
) -> ::std::result::Result<Self, V::Error> {
EnumTypeFoldableImpl!(@FoldVariants(self, folder) input($($variants)*) output())
EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output())
}
}
};
fn visit_with<V: $crate::ty::fold::TypeVisitor<$tcx>>(
(impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path {
$($variants:tt)*
} $(where $($wc:tt)*)*) => {
impl<$($p),*> $crate::ty::visit::TypeVisitable<$tcx> for $s
$(where $($wc)*)*
{
fn visit_with<V: $crate::ty::visit::TypeVisitor<$tcx>>(
&self,
visitor: &mut V,
) -> ::std::ops::ControlFlow<V::BreakTy> {
EnumTypeFoldableImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output())
}
}
};
@ -120,7 +130,7 @@ macro_rules! EnumTypeFoldableImpl {
(@FoldVariants($this:expr, $folder:expr)
input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeFoldableImpl!(
EnumTypeTraversalImpl!(
@FoldVariants($this, $folder)
input($($input)*)
output(
@ -137,7 +147,7 @@ macro_rules! EnumTypeFoldableImpl {
(@FoldVariants($this:expr, $folder:expr)
input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeFoldableImpl!(
EnumTypeTraversalImpl!(
@FoldVariants($this, $folder)
input($($input)*)
output(
@ -155,7 +165,7 @@ macro_rules! EnumTypeFoldableImpl {
(@FoldVariants($this:expr, $folder:expr)
input( ($variant:path), $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeFoldableImpl!(
EnumTypeTraversalImpl!(
@FoldVariants($this, $folder)
input($($input)*)
output(
@ -174,12 +184,12 @@ macro_rules! EnumTypeFoldableImpl {
(@VisitVariants($this:expr, $visitor:expr)
input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeFoldableImpl!(
EnumTypeTraversalImpl!(
@VisitVariants($this, $visitor)
input($($input)*)
output(
$variant ( $($variant_arg),* ) => {
$($crate::ty::fold::TypeFoldable::visit_with(
$($crate::ty::visit::TypeVisitable::visit_with(
$variant_arg, $visitor
)?;)*
::std::ops::ControlFlow::CONTINUE
@ -192,12 +202,12 @@ macro_rules! EnumTypeFoldableImpl {
(@VisitVariants($this:expr, $visitor:expr)
input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeFoldableImpl!(
EnumTypeTraversalImpl!(
@VisitVariants($this, $visitor)
input($($input)*)
output(
$variant { $($variant_arg),* } => {
$($crate::ty::fold::TypeFoldable::visit_with(
$($crate::ty::visit::TypeVisitable::visit_with(
$variant_arg, $visitor
)?;)*
::std::ops::ControlFlow::CONTINUE
@ -210,7 +220,7 @@ macro_rules! EnumTypeFoldableImpl {
(@VisitVariants($this:expr, $visitor:expr)
input( ($variant:path), $($input:tt)*)
output( $($output:tt)*) ) => {
EnumTypeFoldableImpl!(
EnumTypeTraversalImpl!(
@VisitVariants($this, $visitor)
input($($input)*)
output(

View File

@ -100,7 +100,7 @@ impl From<InjectedExpressionId> for ExpressionOperandId {
}
}
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)]
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
pub enum CoverageKind {
Counter {
function_source_hash: u64,
@ -148,18 +148,8 @@ impl Debug for CoverageKind {
}
}
#[derive(
Clone,
TyEncodable,
TyDecodable,
Hash,
HashStable,
TypeFoldable,
PartialEq,
Eq,
PartialOrd,
Ord
)]
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct CodeRegion {
pub file_name: Symbol,
pub start_line: u32,
@ -178,7 +168,8 @@ impl Debug for CodeRegion {
}
}
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)]
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum Op {
Subtract,
Add,

View File

@ -58,6 +58,6 @@ impl<CTX> HashStable<CTX> for GraphIsCyclicCache {
}
}
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
GraphIsCyclicCache,
}

View File

@ -29,7 +29,7 @@ impl From<ErrorGuaranteed> for ErrorHandled {
}
}
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
ErrorHandled,
}

View File

@ -1,8 +1,8 @@
use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId};
use crate::mir;
use crate::ty::fold::TypeFoldable;
use crate::ty::subst::InternalSubsts;
use crate::ty::visit::TypeVisitable;
use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt};
use rustc_hir::def_id::DefId;
use rustc_span::{Span, DUMMY_SP};

View File

@ -8,9 +8,10 @@ use crate::mir::interpret::{
use crate::mir::traversal::PostorderCache;
use crate::mir::visit::MirVisitable;
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable, TypeVisitor};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use crate::ty::{self, List, Ty, TyCtxt};
use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
@ -68,6 +69,7 @@ pub use terminator::*;
pub mod traversal;
mod type_foldable;
mod type_visitable;
pub mod visit;
pub use self::generic_graph::graphviz_safe_def_name;
@ -136,7 +138,7 @@ impl MirPhase {
/// Where a specific `mir::Body` comes from.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable)]
#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
pub struct MirSource<'tcx> {
pub instance: InstanceDef<'tcx>,
@ -166,7 +168,7 @@ impl<'tcx> MirSource<'tcx> {
}
}
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)]
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub struct GeneratorInfo<'tcx> {
/// The yield type of the function, if it is a generator.
pub yield_ty: Option<Ty<'tcx>>,
@ -183,7 +185,7 @@ pub struct GeneratorInfo<'tcx> {
}
/// The lowered representation of a single function.
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)]
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub struct Body<'tcx> {
/// A list of basic blocks. References to basic block use a newtyped index type [`BasicBlock`]
/// that indexes into this vector.
@ -601,7 +603,7 @@ impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
}
}
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable)]
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub enum ClearCrossCrate<T> {
Clear,
Set(T),
@ -762,7 +764,7 @@ pub enum ImplicitSelfKind {
None,
}
TrivialTypeFoldableAndLiftImpls! { BindingForm<'tcx>, }
TrivialTypeTraversalAndLiftImpls! { BindingForm<'tcx>, }
mod binding_form_impl {
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@ -807,7 +809,7 @@ pub struct BlockTailInfo {
///
/// This can be a binding declared by the user, a temporary inserted by the compiler, a function
/// argument, or the return place.
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct LocalDecl<'tcx> {
/// Whether this is a mutable binding (i.e., `let x` or `let mut x`).
///
@ -942,7 +944,7 @@ static_assert_size!(LocalDecl<'_>, 56);
///
/// Not used for non-StaticRef temporaries, the return place, or anonymous
/// function parameters.
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub enum LocalInfo<'tcx> {
/// A user-defined local variable or function parameter
///
@ -1081,7 +1083,7 @@ impl<'tcx> LocalDecl<'tcx> {
}
}
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub enum VarDebugInfoContents<'tcx> {
/// NOTE(eddyb) There's an unenforced invariant that this `Place` is
/// based on a `Local`, not a `Static`, and contains no indexing.
@ -1099,7 +1101,7 @@ impl<'tcx> Debug for VarDebugInfoContents<'tcx> {
}
/// Debug information pertaining to a user variable.
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct VarDebugInfo<'tcx> {
pub name: Symbol,
@ -1155,7 +1157,7 @@ impl BasicBlock {
// BasicBlockData
/// See [`BasicBlock`] for documentation on what basic blocks are at a high level.
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct BasicBlockData<'tcx> {
/// List of statements in this block.
pub statements: Vec<Statement<'tcx>>,
@ -1392,7 +1394,7 @@ impl<O: fmt::Debug> fmt::Debug for AssertKind<O> {
///////////////////////////////////////////////////////////////////////////
// Statements
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct Statement<'tcx> {
pub source_info: SourceInfo,
pub kind: StatementKind<'tcx>,
@ -1758,7 +1760,7 @@ impl SourceScope {
}
}
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct SourceScopeData<'tcx> {
pub span: Span,
pub parent_scope: Option<SourceScope>,
@ -2524,7 +2526,7 @@ impl<'tcx> ConstantKind<'tcx> {
/// The first will lead to the constraint `w: &'1 str` (for some
/// inferred region `'1`). The second will lead to the constraint `w:
/// &'static str`.
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct UserTypeProjections {
pub contents: Vec<(UserTypeProjection, Span)>,
}
@ -2641,7 +2643,7 @@ impl UserTypeProjection {
}
}
TrivialTypeFoldableAndLiftImpls! { ProjectionKind, }
TrivialTypeTraversalAndLiftImpls! { ProjectionKind, }
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
@ -2650,7 +2652,9 @@ impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
projs: self.projs.try_fold_with(folder)?,
})
}
}
impl<'tcx> TypeVisitable<'tcx> for UserTypeProjection {
fn visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<Vs::BreakTy> {
self.base.visit_with(visitor)
// Note: there's nothing in `self.proj` to visit.

View File

@ -73,6 +73,6 @@ impl<CTX> HashStable<CTX> for PredecessorCache {
}
}
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
PredecessorCache,
}

View File

@ -161,7 +161,7 @@ rustc_index::newtype_index! {
}
/// The layout of generator state.
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct GeneratorLayout<'tcx> {
/// The type of every local stored inside the generator.
pub field_tys: IndexVec<GeneratorSavedLocal, Ty<'tcx>>,

View File

@ -73,6 +73,6 @@ impl<CTX> HashStable<CTX> for SwitchSourceCache {
}
}
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
SwitchSourceCache,
}

View File

@ -179,7 +179,8 @@ pub enum BorrowKind {
/// Not all of these are allowed at every [`MirPhase`]. Check the documentation there to see which
/// ones you do not have to worry about. The MIR validator will generally enforce such restrictions,
/// causing an ICE if they are violated.
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)]
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum StatementKind<'tcx> {
/// Assign statements roughly correspond to an assignment in Rust proper (`x = ...`) except
/// without the possibility of dropping the previous value (that must be done separately, if at
@ -376,13 +377,15 @@ pub enum FakeReadCause {
ForIndex,
}
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)]
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct Coverage {
pub kind: CoverageKind,
pub code_region: Option<CodeRegion>,
}
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)]
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct CopyNonOverlapping<'tcx> {
pub src: Operand<'tcx>,
pub dst: Operand<'tcx>,
@ -672,7 +675,8 @@ pub enum AssertKind<O> {
ResumedAfterPanic(GeneratorKind),
}
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable)]
#[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum InlineAsmOperand<'tcx> {
In {
reg: InlineAsmRegOrRegClass,

View File

@ -9,7 +9,7 @@ use crate::ty::{self, Ty, TyCtxt};
use rustc_hir as hir;
use rustc_target::abi::VariantIdx;
#[derive(Copy, Clone, Debug, TypeFoldable)]
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct PlaceTy<'tcx> {
pub ty: Ty<'tcx>,
/// Downcast to a particular variant of an enum or a generator, if included.

View File

@ -384,6 +384,6 @@ impl<CTX> HashStable<CTX> for PostorderCache {
}
}
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
PostorderCache,
}

View File

@ -4,7 +4,7 @@ use super::*;
use crate::ty;
use rustc_data_structures::functor::IdFunctor;
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
BlockTailInfo,
MirPhase,
SourceInfo,
@ -89,65 +89,12 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
};
Ok(Terminator { source_info: self.source_info, kind })
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
use crate::mir::TerminatorKind::*;
match self.kind {
SwitchInt { ref discr, switch_ty, .. } => {
discr.visit_with(visitor)?;
switch_ty.visit_with(visitor)
}
Drop { ref place, .. } => place.visit_with(visitor),
DropAndReplace { ref place, ref value, .. } => {
place.visit_with(visitor)?;
value.visit_with(visitor)
}
Yield { ref value, .. } => value.visit_with(visitor),
Call { ref func, ref args, ref destination, .. } => {
destination.visit_with(visitor)?;
func.visit_with(visitor)?;
args.visit_with(visitor)
}
Assert { ref cond, ref msg, .. } => {
cond.visit_with(visitor)?;
use AssertKind::*;
match msg {
BoundsCheck { ref len, ref index } => {
len.visit_with(visitor)?;
index.visit_with(visitor)
}
Overflow(_, l, r) => {
l.visit_with(visitor)?;
r.visit_with(visitor)
}
OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
op.visit_with(visitor)
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
}
}
InlineAsm { ref operands, .. } => operands.visit_with(visitor),
Goto { .. }
| Resume
| Abort
| Return
| GeneratorDrop
| Unreachable
| FalseEdge { .. }
| FalseUnwind { .. } => ControlFlow::CONTINUE,
}
}
}
impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
Ok(self)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
@ -157,21 +104,12 @@ impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
projection: self.projection.try_fold_with(folder)?,
})
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.local.visit_with(visitor)?;
self.projection.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_place_elems(v))
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
@ -224,55 +162,6 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
}
})
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
use crate::mir::Rvalue::*;
match *self {
Use(ref op) => op.visit_with(visitor),
Repeat(ref op, _) => op.visit_with(visitor),
ThreadLocalRef(did) => did.visit_with(visitor),
Ref(region, _, ref place) => {
region.visit_with(visitor)?;
place.visit_with(visitor)
}
AddressOf(_, ref place) => place.visit_with(visitor),
Len(ref place) => place.visit_with(visitor),
Cast(_, ref op, ty) => {
op.visit_with(visitor)?;
ty.visit_with(visitor)
}
BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => {
rhs.visit_with(visitor)?;
lhs.visit_with(visitor)
}
UnaryOp(_, ref val) => val.visit_with(visitor),
Discriminant(ref place) => place.visit_with(visitor),
NullaryOp(_, ty) => ty.visit_with(visitor),
Aggregate(ref kind, ref fields) => {
match **kind {
AggregateKind::Array(ty) => {
ty.visit_with(visitor)?;
}
AggregateKind::Tuple => {}
AggregateKind::Adt(_, _, substs, user_ty, _) => {
substs.visit_with(visitor)?;
user_ty.visit_with(visitor)?;
}
AggregateKind::Closure(_, substs) => {
substs.visit_with(visitor)?;
}
AggregateKind::Generator(_, substs, _) => {
substs.visit_with(visitor)?;
}
}
fields.visit_with(visitor)
}
ShallowInitBox(ref op, ty) => {
op.visit_with(visitor)?;
ty.visit_with(visitor)
}
}
}
}
impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
@ -283,13 +172,6 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
Operand::Constant(c) => Operand::Constant(c.try_fold_with(folder)?),
})
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match *self {
Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
Operand::Constant(ref c) => c.visit_with(visitor),
}
}
}
impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
@ -307,43 +189,24 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceElem<'tcx> {
Subslice { from, to, from_end } => Subslice { from, to, from_end },
})
}
fn visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<Vs::BreakTy> {
use crate::mir::ProjectionElem::*;
match self {
Field(_, ty) => ty.visit_with(visitor),
Index(v) => v.visit_with(visitor),
_ => ControlFlow::CONTINUE,
}
}
}
impl<'tcx> TypeFoldable<'tcx> for Field {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
Ok(self)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
Ok(self)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
Ok(self)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
@ -354,10 +217,6 @@ impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
literal: self.literal.try_fold_with(folder)?,
})
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.literal.visit_with(visitor)?;
self.user_ty.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
@ -365,10 +224,6 @@ impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_mir_const(self)
}
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_mir_const(*self)
}
}
impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> {
@ -381,11 +236,4 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> {
ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match *self {
ConstantKind::Ty(c) => c.visit_with(visitor),
ConstantKind::Val(_, t) => t.visit_with(visitor),
}
}
}

View File

@ -0,0 +1,186 @@
//! `TypeVisitable` implementations for MIR types
use super::*;
use crate::ty;
impl<'tcx> TypeVisitable<'tcx> for Terminator<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
use crate::mir::TerminatorKind::*;
match self.kind {
SwitchInt { ref discr, switch_ty, .. } => {
discr.visit_with(visitor)?;
switch_ty.visit_with(visitor)
}
Drop { ref place, .. } => place.visit_with(visitor),
DropAndReplace { ref place, ref value, .. } => {
place.visit_with(visitor)?;
value.visit_with(visitor)
}
Yield { ref value, .. } => value.visit_with(visitor),
Call { ref func, ref args, ref destination, .. } => {
destination.visit_with(visitor)?;
func.visit_with(visitor)?;
args.visit_with(visitor)
}
Assert { ref cond, ref msg, .. } => {
cond.visit_with(visitor)?;
use AssertKind::*;
match msg {
BoundsCheck { ref len, ref index } => {
len.visit_with(visitor)?;
index.visit_with(visitor)
}
Overflow(_, l, r) => {
l.visit_with(visitor)?;
r.visit_with(visitor)
}
OverflowNeg(op) | DivisionByZero(op) | RemainderByZero(op) => {
op.visit_with(visitor)
}
ResumedAfterReturn(_) | ResumedAfterPanic(_) => ControlFlow::CONTINUE,
}
}
InlineAsm { ref operands, .. } => operands.visit_with(visitor),
Goto { .. }
| Resume
| Abort
| Return
| GeneratorDrop
| Unreachable
| FalseEdge { .. }
| FalseUnwind { .. } => ControlFlow::CONTINUE,
}
}
}
impl<'tcx> TypeVisitable<'tcx> for GeneratorKind {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
impl<'tcx> TypeVisitable<'tcx> for Place<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.local.visit_with(visitor)?;
self.projection.visit_with(visitor)
}
}
impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
}
impl<'tcx> TypeVisitable<'tcx> for Rvalue<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
use crate::mir::Rvalue::*;
match *self {
Use(ref op) => op.visit_with(visitor),
Repeat(ref op, _) => op.visit_with(visitor),
ThreadLocalRef(did) => did.visit_with(visitor),
Ref(region, _, ref place) => {
region.visit_with(visitor)?;
place.visit_with(visitor)
}
AddressOf(_, ref place) => place.visit_with(visitor),
Len(ref place) => place.visit_with(visitor),
Cast(_, ref op, ty) => {
op.visit_with(visitor)?;
ty.visit_with(visitor)
}
BinaryOp(_, box (ref rhs, ref lhs)) | CheckedBinaryOp(_, box (ref rhs, ref lhs)) => {
rhs.visit_with(visitor)?;
lhs.visit_with(visitor)
}
UnaryOp(_, ref val) => val.visit_with(visitor),
Discriminant(ref place) => place.visit_with(visitor),
NullaryOp(_, ty) => ty.visit_with(visitor),
Aggregate(ref kind, ref fields) => {
match **kind {
AggregateKind::Array(ty) => {
ty.visit_with(visitor)?;
}
AggregateKind::Tuple => {}
AggregateKind::Adt(_, _, substs, user_ty, _) => {
substs.visit_with(visitor)?;
user_ty.visit_with(visitor)?;
}
AggregateKind::Closure(_, substs) => {
substs.visit_with(visitor)?;
}
AggregateKind::Generator(_, substs, _) => {
substs.visit_with(visitor)?;
}
}
fields.visit_with(visitor)
}
ShallowInitBox(ref op, ty) => {
op.visit_with(visitor)?;
ty.visit_with(visitor)
}
}
}
}
impl<'tcx> TypeVisitable<'tcx> for Operand<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match *self {
Operand::Copy(ref place) | Operand::Move(ref place) => place.visit_with(visitor),
Operand::Constant(ref c) => c.visit_with(visitor),
}
}
}
impl<'tcx> TypeVisitable<'tcx> for PlaceElem<'tcx> {
fn visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> ControlFlow<Vs::BreakTy> {
use crate::mir::ProjectionElem::*;
match self {
Field(_, ty) => ty.visit_with(visitor),
Index(v) => v.visit_with(visitor),
_ => ControlFlow::CONTINUE,
}
}
}
impl<'tcx> TypeVisitable<'tcx> for Field {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
impl<'tcx> TypeVisitable<'tcx> for GeneratorSavedLocal {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
}
impl<'tcx> TypeVisitable<'tcx> for Constant<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.literal.visit_with(visitor)?;
self.user_ty.visit_with(visitor)
}
}
impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_mir_const(*self)
}
}
impl<'tcx> TypeSuperVisitable<'tcx> for ConstantKind<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match *self {
ConstantKind::Ty(c) => c.visit_with(visitor),
ConstantKind::Val(_, t) => t.visit_with(visitor),
}
}
}

View File

@ -191,18 +191,8 @@ pub enum StmtKind<'tcx> {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Expr<'_>, 104);
#[derive(
Clone,
Debug,
Copy,
PartialEq,
Eq,
Hash,
HashStable,
TyEncodable,
TyDecodable,
TypeFoldable
)]
#[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct LocalVarId(pub hir::HirId);
/// A THIR expression.

View File

@ -42,7 +42,7 @@ impl From<ErrorGuaranteed> for NotConstEvaluatable {
}
}
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
NotConstEvaluatable,
}

View File

@ -390,7 +390,7 @@ impl<'tcx> chalk_ir::interner::HasInterner for RustInterner<'tcx> {
}
/// A chalk environment and goal.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub struct ChalkEnvironmentAndGoal<'tcx> {
pub environment: &'tcx ty::List<ty::Predicate<'tcx>>,
pub goal: ty::Predicate<'tcx>,

View File

@ -523,7 +523,7 @@ pub struct DerivedObligationCause<'tcx> {
pub parent_code: InternedObligationCauseCode<'tcx>,
}
#[derive(Clone, Debug, TypeFoldable, Lift)]
#[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
pub enum SelectionError<'tcx> {
/// The trait is not implemented.
Unimplemented,
@ -592,7 +592,8 @@ pub type SelectionResult<'tcx, T> = Result<Option<T>, SelectionError<'tcx>>;
/// ### The type parameter `N`
///
/// See explanation on `ImplSourceUserDefinedData`.
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum ImplSource<'tcx, N> {
/// ImplSource identifying a particular impl.
UserDefined(ImplSourceUserDefinedData<'tcx, N>),
@ -753,14 +754,16 @@ impl<'tcx, N> ImplSource<'tcx, N> {
/// is `Obligation`, as one might expect. During codegen, however, this
/// is `()`, because codegen only requires a shallow resolution of an
/// impl, and nested obligations are satisfied later.
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceUserDefinedData<'tcx, N> {
pub impl_def_id: DefId,
pub substs: SubstsRef<'tcx>,
pub nested: Vec<N>,
}
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceGeneratorData<'tcx, N> {
pub generator_def_id: DefId,
pub substs: SubstsRef<'tcx>,
@ -769,7 +772,8 @@ pub struct ImplSourceGeneratorData<'tcx, N> {
pub nested: Vec<N>,
}
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceClosureData<'tcx, N> {
pub closure_def_id: DefId,
pub substs: SubstsRef<'tcx>,
@ -778,13 +782,15 @@ pub struct ImplSourceClosureData<'tcx, N> {
pub nested: Vec<N>,
}
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceAutoImplData<N> {
pub trait_def_id: DefId,
pub nested: Vec<N>,
}
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceTraitUpcastingData<'tcx, N> {
/// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
@ -798,12 +804,14 @@ pub struct ImplSourceTraitUpcastingData<'tcx, N> {
pub nested: Vec<N>,
}
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceBuiltinData<N> {
pub nested: Vec<N>,
}
#[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceObjectData<'tcx, N> {
/// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`.
pub upcast_trait_ref: ty::PolyTraitRef<'tcx>,
@ -817,7 +825,8 @@ pub struct ImplSourceObjectData<'tcx, N> {
pub nested: Vec<N>,
}
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceFnPointerData<'tcx, N> {
pub fn_ty: Ty<'tcx>,
pub nested: Vec<N>,
@ -830,12 +839,14 @@ pub struct ImplSourceDiscriminantKindData;
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)]
pub struct ImplSourcePointeeData;
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceConstDestructData<N> {
pub nested: Vec<N>,
}
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ImplSourceTraitAliasData<'tcx, N> {
pub alias_def_id: DefId,
pub substs: SubstsRef<'tcx>,

View File

@ -24,7 +24,8 @@ pub mod type_op {
use rustc_hir::def_id::DefId;
use std::fmt;
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct AscribeUserType<'tcx> {
pub mir_ty: Ty<'tcx>,
pub def_id: DefId,
@ -37,19 +38,22 @@ pub mod type_op {
}
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct Eq<'tcx> {
pub a: Ty<'tcx>,
pub b: Ty<'tcx>,
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct Subtype<'tcx> {
pub sub: Ty<'tcx>,
pub sup: Ty<'tcx>,
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ProvePredicate<'tcx> {
pub predicate: Predicate<'tcx>,
}
@ -60,7 +64,8 @@ pub mod type_op {
}
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, Lift)]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct Normalize<T> {
pub value: T,
}
@ -107,7 +112,7 @@ impl<'tcx> From<TypeError<'tcx>> for NoSolution {
}
}
#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)]
#[derive(Clone, Debug, Default, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct DropckOutlivesResult<'tcx> {
pub kinds: Vec<GenericArg<'tcx>>,
pub overflows: Vec<Ty<'tcx>>,
@ -208,7 +213,7 @@ pub struct MethodAutoderefBadTy<'tcx> {
}
/// Result from the `normalize_projection_ty` query.
#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)]
#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct NormalizationResult<'tcx> {
/// Result of normalization.
pub normalized_ty: Ty<'tcx>,
@ -221,7 +226,7 @@ pub struct NormalizationResult<'tcx> {
/// case they are called implied bounds). They are fed to the
/// `OutlivesEnv` which in turn is supplied to the region checker and
/// other parts of the inference system.
#[derive(Clone, Debug, TypeFoldable, Lift)]
#[derive(Clone, Debug, TypeFoldable, TypeVisitable, Lift)]
pub enum OutlivesBound<'tcx> {
RegionSubRegion(ty::Region<'tcx>, ty::Region<'tcx>),
RegionSubParam(ty::Region<'tcx>, ty::ParamTy),

View File

@ -103,7 +103,7 @@ pub type EvaluationCache<'tcx> = Cache<
/// required for associated types to work in default impls, as the bounds
/// are visible both as projection bounds and as where-clauses from the
/// parameter environment.
#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable)]
#[derive(PartialEq, Eq, Debug, Clone, TypeFoldable, TypeVisitable)]
pub enum SelectionCandidate<'tcx> {
BuiltinCandidate {
/// `false` if there are no *further* obligations.
@ -283,7 +283,7 @@ impl From<ErrorGuaranteed> for OverflowError {
}
}
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
OverflowError,
}

View File

@ -1,5 +1,5 @@
use crate::ty::fast_reject::SimplifiedType;
use crate::ty::fold::TypeFoldable;
use crate::ty::visit::TypeVisitable;
use crate::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;

View File

@ -129,7 +129,7 @@ impl<N: fmt::Debug> fmt::Debug for traits::ImplSourceConstDestructData<N> {
///////////////////////////////////////////////////////////////////////////
// Lift implementations
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
super::IfExpressionCause,
super::ImplSourceDiscriminantKindData,
super::ImplSourcePointeeData,

View File

@ -77,7 +77,7 @@ pub enum PointerCast {
/// At some point, of course, `Box` should move out of the compiler, in which
/// case this is analogous to transforming a struct. E.g., `Box<[i32; 4]>` ->
/// `Box<[i32]>` is an `Adjust::Unsize` with the target `Box<[i32]>`.
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub struct Adjustment<'tcx> {
pub kind: Adjust<'tcx>,
pub target: Ty<'tcx>,
@ -89,7 +89,7 @@ impl<'tcx> Adjustment<'tcx> {
}
}
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub enum Adjust<'tcx> {
/// Go from ! to any type.
NeverToAny,
@ -107,7 +107,8 @@ pub enum Adjust<'tcx> {
/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
/// The target type is `U` in both cases, with the region and mutability
/// being those shared by both the receiver and the returned reference.
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct OverloadedDeref<'tcx> {
pub region: ty::Region<'tcx>,
pub mutbl: hir::Mutability,
@ -165,7 +166,8 @@ impl From<AutoBorrowMutability> for hir::Mutability {
}
}
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum AutoBorrow<'tcx> {
/// Converts from T to &T.
Ref(ty::Region<'tcx>, AutoBorrowMutability),

View File

@ -8,7 +8,7 @@ pub enum BindingMode {
BindByValue(Mutability),
}
TrivialTypeFoldableAndLiftImpls! { BindingMode, }
TrivialTypeTraversalAndLiftImpls! { BindingMode, }
impl BindingMode {
pub fn convert(ba: BindingAnnotation) -> BindingMode {

View File

@ -18,18 +18,8 @@ use self::BorrowKind::*;
// This represents accessing self in the closure structure
pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::from_u32(1);
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
TypeFoldable,
HashStable
)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct UpvarPath {
pub hir_id: hir::HirId,
}
@ -37,7 +27,8 @@ pub struct UpvarPath {
/// Upvars do not get their own `NodeId`. Instead, we use the pair of
/// the original var ID (that is, the root variable that is referenced
/// by the upvar) and the ID of the closure expression.
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct UpvarId {
pub var_path: UpvarPath,
pub closure_expr_id: LocalDefId,
@ -51,7 +42,8 @@ impl UpvarId {
/// Information describing the capture of an upvar. This is computed
/// during `typeck`, specifically by `regionck`.
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum UpvarCapture {
/// Upvar is captured by value. This is always true when the
/// closure is labeled `move`, but can also be true in other cases
@ -139,7 +131,8 @@ impl<'tcx> ClosureKind {
}
/// A composite describing a `Place` that is captured by a closure.
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
#[derive(PartialEq, Clone, Debug, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct CapturedPlace<'tcx> {
/// The `Place` that is captured.
pub place: HirPlace<'tcx>,
@ -284,7 +277,8 @@ pub fn is_ancestor_or_same_capture(
/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
/// for a particular capture as well as identifying the part of the source code
/// that triggered this capture to occur.
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, TypeFoldable, HashStable)]
#[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct CaptureInfo {
/// Expr Id pointing to use that resulted in selecting the current capture kind
///
@ -362,7 +356,8 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc
curr_string
}
#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, TypeFoldable, Copy, HashStable)]
#[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum BorrowKind {
/// Data must be immutable and is aliasable.
ImmBorrow,

View File

@ -2,7 +2,7 @@ use crate::mir::interpret::LitToConstInput;
use crate::mir::ConstantKind;
use crate::ty::{
self, InlineConstSubsts, InlineConstSubstsParts, InternalSubsts, ParamEnv, ParamEnvAnd, Ty,
TyCtxt, TypeFoldable,
TyCtxt, TypeVisitable,
};
use rustc_data_structures::intern::Interned;
use rustc_errors::ErrorGuaranteed;

View File

@ -4,7 +4,7 @@ use crate::mir::interpret::{AllocId, ConstValue, Scalar};
use crate::mir::Promoted;
use crate::ty::subst::{InternalSubsts, SubstsRef};
use crate::ty::ParamEnv;
use crate::ty::{self, TyCtxt, TypeFoldable};
use crate::ty::{self, TyCtxt, TypeVisitable};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;

View File

@ -390,7 +390,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
/// Here, we would store the type `T`, the span of the value `x`, the "scope-span" for
/// the scope that contains `x`, the expr `T` evaluated from, and the span of `foo.await`.
#[derive(TyEncodable, TyDecodable, Clone, Debug, Eq, Hash, PartialEq, HashStable)]
#[derive(TypeFoldable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct GeneratorInteriorTypeCause<'tcx> {
/// Type of the captured binding.
pub ty: Ty<'tcx>,
@ -871,7 +871,7 @@ rustc_index::newtype_index! {
pub type CanonicalUserTypeAnnotations<'tcx> =
IndexVec<UserTypeAnnotationIndex, CanonicalUserTypeAnnotation<'tcx>>;
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, Lift)]
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct CanonicalUserTypeAnnotation<'tcx> {
pub user_ty: CanonicalUserType<'tcx>,
pub span: Span,
@ -931,7 +931,7 @@ impl<'tcx> CanonicalUserType<'tcx> {
/// from constants that are named via paths, like `Foo::<A>::new` and
/// so forth.
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, Lift)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub enum UserType<'tcx> {
Ty(Ty<'tcx>),

View File

@ -3,8 +3,8 @@
use std::ops::ControlFlow;
use crate::ty::{
fold::TypeFoldable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferTy,
PolyTraitPredicate, Ty, TyCtxt, TypeSuperFoldable, TypeVisitor,
visit::TypeVisitable, Const, ConstKind, DefIdTree, ExistentialPredicate, InferTy,
PolyTraitPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor,
};
use rustc_data_structures::fx::FxHashMap;
@ -87,7 +87,7 @@ pub trait IsSuggestable<'tcx> {
impl<'tcx, T> IsSuggestable<'tcx> for T
where
T: TypeFoldable<'tcx>,
T: TypeVisitable<'tcx>,
{
fn is_suggestable(self, tcx: TyCtxt<'tcx>) -> bool {
self.visit_with(&mut IsSuggestableVisitor { tcx }).is_continue()

View File

@ -1,5 +1,6 @@
use crate::mir;
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use crate::ty::visit::TypeVisitable;
use crate::ty::{self, Ty, TyCtxt, TypeFlags};
pub(super) fn provide(providers: &mut ty::query::Providers) {

View File

@ -13,7 +13,7 @@ use rustc_target::spec::abi;
use std::borrow::Cow;
use std::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
pub struct ExpectedFound<T> {
pub expected: T,
pub found: T,
@ -30,7 +30,7 @@ impl<T> ExpectedFound<T> {
}
// Data structures used in type unification
#[derive(Clone, Debug, TypeFoldable)]
#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
pub enum TypeError<'tcx> {
Mismatch,
ConstnessMismatch(ExpectedFound<ty::BoundConstness>),

View File

@ -1,6 +1,6 @@
use crate::mir::Mutability;
use crate::ty::subst::GenericArgKind;
use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
use crate::ty::{self, Ty, TyCtxt, TypeVisitable};
use rustc_hir::def_id::DefId;
use std::fmt::Debug;
use std::hash::Hash;

View File

@ -1,76 +1,60 @@
//! A generalized traversal mechanism for complex data structures that contain
//! type information.
//! A folding traversal mechanism for complex data structures that contain type
//! information.
//!
//! There are two types of traversal.
//! - Folding. This is a modifying traversal. It consumes the data structure,
//! producing a (possibly) modified version of it. Both fallible and
//! infallible versions are available. The name is potentially
//! confusing, because this traversal is more like `Iterator::map` than
//! `Iterator::fold`.
//! - Visiting. This is a read-only traversal of the data structure.
//! This is a modifying traversal. It consumes the data structure, producing a
//! (possibly) modified version of it. Both fallible and infallible versions are
//! available. The name is potentially confusing, because this traversal is more
//! like `Iterator::map` than `Iterator::fold`.
//!
//! These traversals have limited flexibility. Only a small number of "types of
//! This traversal has limited flexibility. Only a small number of "types of
//! interest" within the complex data structures can receive custom
//! modification (when folding) or custom visitation (when visiting). These are
//! the ones containing the most important type-related information, such as
//! `Ty`, `Predicate`, `Region`, and `Const`.
//! modification. These are the ones containing the most important type-related
//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
//!
//! There are three traits involved in each traversal type.
//! - `TypeFoldable`. This is implemented once for many types. This includes
//! both:
//! There are three groups of traits involved in each traversal.
//! - `TypeFoldable`. This is implemented once for many types, including:
//! - Types of interest, for which the the methods delegate to the
//! folder/visitor.
//! folder.
//! - All other types, including generic containers like `Vec` and `Option`.
//! It defines a "skeleton" of how they should be traversed, for both
//! folding and visiting.
//! It defines a "skeleton" of how they should be folded.
//! - `TypeSuperFoldable`. This is implemented only for each type of interest,
//! and defines the traversal "skeleton" for these types.
//! - `TypeFolder`/`FallibleTypeFolder` (for infallible/fallible folding
//! traversals) or `TypeVisitor` (for visiting traversals). One of these is
//! implemented for each folder/visitor. This defines how types of interest
//! are folded/visited.
//! and defines the folding "skeleton" for these types.
//! - `TypeFolder`/`FallibleTypeFolder. One of these is implemented for each
//! folder. This defines how types of interest are folded.
//!
//! This means each traversal is a mixture of (a) generic traversal operations,
//! and (b) custom fold/visit operations that are specific to the
//! folder/visitor.
//! This means each fold is a mixture of (a) generic folding operations, and (b)
//! custom fold operations that are specific to the folder.
//! - The `TypeFoldable` impls handle most of the traversal, and call into
//! `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` when they encounter a
//! type of interest.
//! - A `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` may call into another
//! `TypeFoldable` impl, because some of the types of interest are recursive
//! and can contain other types of interest.
//! - A `TypeFolder`/`FallibleTypeFolder`/`TypeVisitor` may also call into
//! a `TypeSuperFoldable` impl, because each folder/visitor might provide
//! custom handling only for some types of interest, or only for some
//! variants of each type of interest, and then use default traversal for the
//! remaining cases.
//! `TypeFolder`/`FallibleTypeFolder` when they encounter a type of interest.
//! - A `TypeFolder`/`FallibleTypeFolder` may call into another `TypeFoldable`
//! impl, because some of the types of interest are recursive and can contain
//! other types of interest.
//! - A `TypeFolder`/`FallibleTypeFolder` may also call into a `TypeSuperFoldable`
//! impl, because each folder might provide custom handling only for some types
//! of interest, or only for some variants of each type of interest, and then
//! use default traversal for the remaining cases.
//!
//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
//! TypeFoldable`, and an instance `s = S(ty, u)`, it would be visited like so:
//! TypeFoldable`, and an instance `s = S(ty, u)`, it would be folded like so:
//! ```text
//! s.visit_with(visitor) calls
//! - ty.visit_with(visitor) calls
//! - visitor.visit_ty(ty) may call
//! - ty.super_visit_with(visitor)
//! - u.visit_with(visitor)
//! s.fold_with(folder) calls
//! - ty.fold_with(folder) calls
//! - folder.fold_ty(ty) may call
//! - ty.super_fold_with(folder)
//! - u.fold_with(folder)
//! ```
use crate::mir;
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
use rustc_errors::ErrorGuaranteed;
use crate::ty::{self, Binder, Ty, TyCtxt, TypeVisitable};
use rustc_hir::def_id::DefId;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sso::SsoHashSet;
use std::collections::BTreeMap;
use std::fmt;
use std::ops::ControlFlow;
/// This trait is implemented for every type that can be folded/visited,
/// This trait is implemented for every type that can be folded,
/// providing the skeleton of the traversal.
///
/// To implement this conveniently, use the derive macro located in
/// `rustc_macros`.
pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
pub trait TypeFoldable<'tcx>: TypeVisitable<'tcx> {
/// The entry point for folding. To fold a value `t` with a folder `f`
/// call: `t.try_fold_with(f)`.
///
@ -89,115 +73,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
fn fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
self.try_fold_with(folder).into_ok()
}
/// The entry point for visiting. To visit a value `t` with a visitor `v`
/// call: `t.visit_with(v)`.
///
/// For most types, this just traverses the value, calling `visit_with` on
/// each field/element.
///
/// For types of interest (such as `Ty`), the implementation of this method
/// that calls a visitor method specifically for that type (such as
/// `V::visit_ty`). This is where control transfers from `TypeFoldable` to
/// `TypeVisitor`.
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
/// Returns `true` if `self` has any late-bound regions that are either
/// bound by `binder` or bound by some binder outside of `binder`.
/// If `binder` is `ty::INNERMOST`, this indicates whether
/// there are any late-bound regions that appear free.
fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break()
}
/// Returns `true` if this `self` has any regions that escape `binder` (and
/// hence are not bound by it).
fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
self.has_vars_bound_at_or_above(binder.shifted_in(1))
}
fn has_escaping_bound_vars(&self) -> bool {
self.has_vars_bound_at_or_above(ty::INNERMOST)
}
#[instrument(level = "trace")]
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
}
fn has_projections(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_PROJECTION)
}
fn has_opaque_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
}
fn references_error(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_ERROR)
}
fn error_reported(&self) -> Option<ErrorGuaranteed> {
if self.references_error() {
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
} else {
None
}
}
fn has_param_types_or_consts(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
}
fn has_infer_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_INFER)
}
fn has_infer_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER)
}
fn has_infer_types_or_consts(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER)
}
fn needs_infer(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_INFER)
}
fn has_placeholders(&self) -> bool {
self.has_type_flags(
TypeFlags::HAS_RE_PLACEHOLDER
| TypeFlags::HAS_TY_PLACEHOLDER
| TypeFlags::HAS_CT_PLACEHOLDER,
)
}
fn needs_subst(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_SUBST)
}
/// "Free" regions in this context means that it has any region
/// that is not (a) erased or (b) late-bound.
fn has_free_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
}
fn has_erased_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_ERASED)
}
/// True if there are any un-erased free regions.
fn has_erasable_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
}
/// Indicates whether this value references only 'global'
/// generic parameters that are the same regardless of what fn we are
/// in. This is used for caching.
fn is_global(&self) -> bool {
!self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
}
/// True if there are any late-bound regions
fn has_late_bound_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
}
/// Indicates whether this value still has parameters/placeholders/inference variables
/// which could be replaced later, in a way that would change the results of `impl`
/// specialization.
fn still_further_specializable(&self) -> bool {
self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
}
}
// This trait is implemented for types of interest.
@ -219,14 +94,6 @@ pub trait TypeSuperFoldable<'tcx>: TypeFoldable<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(self, folder: &mut F) -> Self {
self.try_super_fold_with(folder).into_ok()
}
/// Provides a default visit for a type of interest. This should only be
/// called within `TypeVisitor` methods, when a non-custom traversal is
/// desired for the value of the type of interest passed to that method.
/// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call
/// `ty.super_visit_with(self)`, but any other visiting should be done
/// with `xyz.visit_with(self)`.
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
}
/// This trait is implemented for every infallible folding traversal. There is
@ -376,44 +243,6 @@ where
}
}
/// This trait is implemented for every visiting traversal. There is a visit
/// method defined for every type of interest. Each such method has a default
/// that recurses into the type's fields in a non-custom fashion.
pub trait TypeVisitor<'tcx>: Sized {
type BreakTy = !;
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
t.super_visit_with(self)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
t.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
r.super_visit_with(self)
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
c.super_visit_with(self)
}
fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
uv.super_visit_with(self)
}
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
p.super_visit_with(self)
}
fn visit_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> {
c.super_visit_with(self)
}
}
///////////////////////////////////////////////////////////////////////////
// Some sample folders
@ -472,99 +301,6 @@ impl<'tcx> TyCtxt<'tcx> {
{
value.fold_with(&mut RegionFolder::new(self, &mut f))
}
/// Invoke `callback` on every region appearing free in `value`.
pub fn for_each_free_region(
self,
value: &impl TypeFoldable<'tcx>,
mut callback: impl FnMut(ty::Region<'tcx>),
) {
self.any_free_region_meets(value, |r| {
callback(r);
false
});
}
/// Returns `true` if `callback` returns true for every region appearing free in `value`.
pub fn all_free_regions_meet(
self,
value: &impl TypeFoldable<'tcx>,
mut callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
!self.any_free_region_meets(value, |r| !callback(r))
}
/// Returns `true` if `callback` returns true for some region appearing free in `value`.
pub fn any_free_region_meets(
self,
value: &impl TypeFoldable<'tcx>,
callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
struct RegionVisitor<F> {
/// The index of a binder *just outside* the things we have
/// traversed. If we encounter a bound region bound by this
/// binder or one outer to it, it appears free. Example:
///
/// ```ignore (illustrative)
/// for<'a> fn(for<'b> fn(), T)
/// // ^ ^ ^ ^
/// // | | | | here, would be shifted in 1
/// // | | | here, would be shifted in 2
/// // | | here, would be `INNERMOST` shifted in by 1
/// // | here, initially, binder would be `INNERMOST`
/// ```
///
/// You see that, initially, *any* bound value is free,
/// because we've not traversed any binders. As we pass
/// through a binder, we shift the `outer_index` by 1 to
/// account for the new binder that encloses us.
outer_index: ty::DebruijnIndex,
callback: F,
}
impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
where
F: FnMut(ty::Region<'tcx>) -> bool,
{
type BreakTy = ();
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.outer_index.shift_in(1);
let result = t.super_visit_with(self);
self.outer_index.shift_out(1);
result
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match *r {
ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => {
ControlFlow::CONTINUE
}
_ => {
if (self.callback)(r) {
ControlFlow::BREAK
} else {
ControlFlow::CONTINUE
}
}
}
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
// We're only interested in types involving regions
if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
ty.super_visit_with(self)
} else {
ControlFlow::CONTINUE
}
}
}
value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }).is_break()
}
}
/// Folds over the substructure of a type, visiting its component
@ -861,45 +597,6 @@ impl<'tcx> TyCtxt<'tcx> {
)
}
/// 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
/// variables will also be equated.
pub fn collect_constrained_late_bound_regions<T>(
self,
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
T: TypeFoldable<'tcx>,
{
self.collect_late_bound_regions(value, true)
}
/// Returns a set of all late-bound regions that appear in `value` anywhere.
pub fn collect_referenced_late_bound_regions<T>(
self,
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
T: TypeFoldable<'tcx>,
{
self.collect_late_bound_regions(value, false)
}
fn collect_late_bound_regions<T>(
self,
value: &Binder<'tcx, T>,
just_constraint: bool,
) -> FxHashSet<ty::BoundRegionKind>
where
T: TypeFoldable<'tcx>,
{
let mut collector = LateBoundRegionsCollector::new(just_constraint);
let result = value.as_ref().skip_binder().visit_with(&mut collector);
assert!(result.is_continue()); // should never have stopped early
collector.regions
}
/// Replaces any late-bound regions bound in `value` with `'erased`. Useful in codegen but also
/// method lookup and a few other places where precise region relationships are not required.
pub fn erase_late_bound_regions<T>(self, value: Binder<'tcx, T>) -> T
@ -940,103 +637,6 @@ impl<'tcx> TyCtxt<'tcx> {
}
}
pub struct ValidateBoundVars<'tcx> {
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
binder_index: ty::DebruijnIndex,
// We may encounter the same variable at different levels of binding, so
// this can't just be `Ty`
visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
}
impl<'tcx> ValidateBoundVars<'tcx> {
pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self {
ValidateBoundVars {
bound_vars,
binder_index: ty::INNERMOST,
visited: SsoHashSet::default(),
}
}
}
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
type BreakTy = ();
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.binder_index.shift_in(1);
let result = t.super_visit_with(self);
self.binder_index.shift_out(1);
result
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if t.outer_exclusive_binder() < self.binder_index
|| !self.visited.insert((self.binder_index, t))
{
return ControlFlow::BREAK;
}
match *t.kind() {
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
if self.bound_vars.len() <= bound_ty.var.as_usize() {
bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
}
let list_var = self.bound_vars[bound_ty.var.as_usize()];
match list_var {
ty::BoundVariableKind::Ty(kind) => {
if kind != bound_ty.kind {
bug!(
"Mismatched type kinds: {:?} doesn't var in list {:?}",
bound_ty.kind,
list_var
);
}
}
_ => {
bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var)
}
}
}
_ => (),
};
t.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match *r {
ty::ReLateBound(index, br) if index == self.binder_index => {
if self.bound_vars.len() <= br.var.as_usize() {
bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars);
}
let list_var = self.bound_vars[br.var.as_usize()];
match list_var {
ty::BoundVariableKind::Region(kind) => {
if kind != br.kind {
bug!(
"Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})",
br.kind,
list_var,
self.bound_vars
);
}
}
_ => bug!(
"Mismatched bound variable kinds! Expected region, found {:?}",
list_var
),
}
}
_ => (),
};
r.super_visit_with(self)
}
}
///////////////////////////////////////////////////////////////////////////
// Shifter
//
@ -1141,301 +741,3 @@ where
value.fold_with(&mut Shifter::new(tcx, amount))
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
struct FoundEscapingVars;
/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
/// bound region or a bound type.
///
/// So, for example, consider a type like the following, which has two binders:
///
/// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize))
/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope
/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope
///
/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the
/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
/// fn type*, that type has an escaping region: `'a`.
///
/// Note that what I'm calling an "escaping var" is often just called a "free var". However,
/// we already use the term "free var". It refers to the regions or types that we use to represent
/// bound regions or type params on a fn definition while we are type checking its body.
///
/// To clarify, conceptually there is no particular difference between
/// an "escaping" var and a "free" var. However, there is a big
/// difference in practice. Basically, when "entering" a binding
/// level, one is generally required to do some sort of processing to
/// a bound var, such as replacing it with a fresh/placeholder
/// var, or making an entry in the environment to represent the
/// scope to which it is attached, etc. An escaping var represents
/// a bound var for which this processing has not yet been done.
struct HasEscapingVarsVisitor {
/// Anything bound by `outer_index` or "above" is escaping.
outer_index: ty::DebruijnIndex,
}
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars;
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.outer_index.shift_in(1);
let result = t.super_visit_with(self);
self.outer_index.shift_out(1);
result
}
#[inline]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
// If the outer-exclusive-binder is *strictly greater* than
// `outer_index`, that means that `t` contains some content
// bound at `outer_index` or above (because
// `outer_exclusive_binder` is always 1 higher than the
// content in `t`). Therefore, `t` has some escaping vars.
if t.outer_exclusive_binder() > self.outer_index {
ControlFlow::Break(FoundEscapingVars)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
// If the region is bound by `outer_index` or anything outside
// of outer index, then it escapes the binders we have
// visited.
if r.bound_at_or_above_binder(self.outer_index) {
ControlFlow::Break(FoundEscapingVars)
} else {
ControlFlow::CONTINUE
}
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
// we don't have a `visit_infer_const` callback, so we have to
// hook in here to catch this case (annoying...), but
// otherwise we do want to remember to visit the rest of the
// const, as it has types/regions embedded in a lot of other
// places.
match ct.kind() {
ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
ControlFlow::Break(FoundEscapingVars)
}
_ => ct.super_visit_with(self),
}
}
#[inline]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
if predicate.outer_exclusive_binder() > self.outer_index {
ControlFlow::Break(FoundEscapingVars)
} else {
ControlFlow::CONTINUE
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
struct FoundFlags;
// FIXME: Optimize for checking for infer flags
struct HasTypeFlagsVisitor {
flags: ty::TypeFlags,
}
impl std::fmt::Debug for HasTypeFlagsVisitor {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.flags.fmt(fmt)
}
}
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
#[inline]
#[instrument(skip(self), level = "trace")]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = t.flags();
trace!(t.flags=?t.flags());
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(skip(self), level = "trace")]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = r.type_flags();
trace!(r.flags=?flags);
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(level = "trace")]
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = FlagComputation::for_const(c);
trace!(r.flags=?flags);
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(level = "trace")]
fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = FlagComputation::for_unevaluated_const(uv);
trace!(r.flags=?flags);
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(level = "trace")]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!(
"HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
predicate,
predicate.flags(),
self.flags
);
if predicate.flags().intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
}
/// Collects all the late-bound regions at the innermost binding level
/// into a hash set.
struct LateBoundRegionsCollector {
current_index: ty::DebruijnIndex,
regions: FxHashSet<ty::BoundRegionKind>,
/// `true` if we only want regions that are known to be
/// "constrained" when you equate this type with another type. In
/// particular, if you have e.g., `&'a u32` and `&'b u32`, equating
/// them constraints `'a == 'b`. But if you have `<&'a u32 as
/// Trait>::Foo` and `<&'b u32 as Trait>::Foo`, normalizing those
/// types may mean that `'a` and `'b` don't appear in the results,
/// so they are not considered *constrained*.
just_constrained: bool,
}
impl LateBoundRegionsCollector {
fn new(just_constrained: bool) -> Self {
LateBoundRegionsCollector {
current_index: ty::INNERMOST,
regions: Default::default(),
just_constrained,
}
}
}
impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.current_index.shift_in(1);
let result = t.super_visit_with(self);
self.current_index.shift_out(1);
result
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
// if we are only looking for "constrained" region, we have to
// ignore the inputs to a projection, as they may not appear
// in the normalized form
if self.just_constrained {
if let ty::Projection(..) = t.kind() {
return ControlFlow::CONTINUE;
}
}
t.super_visit_with(self)
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
// if we are only looking for "constrained" region, we have to
// ignore the inputs of an unevaluated const, as they may not appear
// in the normalized form
if self.just_constrained {
if let ty::ConstKind::Unevaluated(..) = c.kind() {
return ControlFlow::CONTINUE;
}
}
c.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ReLateBound(debruijn, br) = *r {
if debruijn == self.current_index {
self.regions.insert(br.kind);
}
}
ControlFlow::CONTINUE
}
}
/// Finds the max universe present
pub struct MaxUniverse {
max_universe: ty::UniverseIndex,
}
impl MaxUniverse {
pub fn new() -> Self {
MaxUniverse { max_universe: ty::UniverseIndex::ROOT }
}
pub fn max_universe(self) -> ty::UniverseIndex {
self.max_universe
}
}
impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Placeholder(placeholder) = t.kind() {
self.max_universe = ty::UniverseIndex::from_u32(
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
);
}
t.super_visit_with(self)
}
fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ConstKind::Placeholder(placeholder) = c.kind() {
self.max_universe = ty::UniverseIndex::from_u32(
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
);
}
c.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::RePlaceholder(placeholder) = *r {
self.max_universe = ty::UniverseIndex::from_u32(
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
);
}
ControlFlow::CONTINUE
}
}

View File

@ -1,7 +1,9 @@
use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::subst::{InternalSubsts, Subst};
use crate::ty::{self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
use crate::ty::{
self, EarlyBinder, SubstsRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitable,
};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
@ -25,7 +27,7 @@ pub struct Instance<'tcx> {
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable)]
#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub enum InstanceDef<'tcx> {
/// A user-defined callable item.
///

View File

@ -2,7 +2,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use crate::mir::{GeneratorLayout, GeneratorSavedLocal};
use crate::ty::normalize_erasing_regions::NormalizationError;
use crate::ty::subst::Subst;
use crate::ty::{self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeFoldable};
use crate::ty::{self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable};
use rustc_ast as ast;
use rustc_attr as attr;
use rustc_hir as hir;

View File

@ -9,9 +9,8 @@
//!
//! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html
pub use self::fold::{
FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitor,
};
pub use self::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
pub use self::AssocItemContainer::*;
pub use self::BorrowKind::*;
pub use self::IntVarValue::*;
@ -110,6 +109,7 @@ pub mod relate;
pub mod subst;
pub mod trait_def;
pub mod util;
pub mod visit;
pub mod vtable;
pub mod walk;
@ -206,7 +206,7 @@ impl MainDefinition {
/// The "header" of an impl is everything outside the body: a Self type, a trait
/// ref (in the case of a trait impl), and a set of predicates (from the
/// bounds / where-clauses).
#[derive(Clone, Debug, TypeFoldable)]
#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct ImplHeader<'tcx> {
pub impl_def_id: DefId,
pub self_ty: Ty<'tcx>,
@ -214,24 +214,14 @@ pub struct ImplHeader<'tcx> {
pub predicates: Vec<Predicate<'tcx>>,
}
#[derive(Copy, Clone, Debug, TypeFoldable)]
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub enum ImplSubject<'tcx> {
Trait(TraitRef<'tcx>),
Inherent(Ty<'tcx>),
}
#[derive(
Copy,
Clone,
PartialEq,
Eq,
Hash,
TyEncodable,
TyDecodable,
HashStable,
Debug,
TypeFoldable
)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum ImplPolarity {
/// `impl Trait for Type`
Positive,
@ -307,18 +297,8 @@ impl fmt::Display for BoundConstness {
}
}
#[derive(
Clone,
Debug,
PartialEq,
Eq,
Copy,
Hash,
TyEncodable,
TyDecodable,
HashStable,
TypeFoldable
)]
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash, TyEncodable, TyDecodable, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct ClosureSizeProfileData<'tcx> {
/// Tuple containing the types of closure captures before the feature `capture_disjoint_fields`
pub before_feature_tys: Ty<'tcx>,
@ -618,7 +598,7 @@ impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub enum PredicateKind<'tcx> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
@ -790,7 +770,7 @@ impl<'tcx> Predicate<'tcx> {
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct TraitPredicate<'tcx> {
pub trait_ref: TraitRef<'tcx>,
@ -869,7 +849,7 @@ impl<'tcx> PolyTraitPredicate<'tcx> {
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct OutlivesPredicate<A, B>(pub A, pub B); // `A: B`
pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
@ -880,7 +860,7 @@ pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicat
/// whether the `a` type is the type that we should label as "expected" when
/// presenting user diagnostics.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct SubtypePredicate<'tcx> {
pub a_is_expected: bool,
pub a: Ty<'tcx>,
@ -890,7 +870,7 @@ pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
/// Encodes that we have to coerce *from* the `a` type to the `b` type.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct CoercePredicate<'tcx> {
pub a: Ty<'tcx>,
pub b: Ty<'tcx>,
@ -898,7 +878,7 @@ pub struct CoercePredicate<'tcx> {
pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub enum Term<'tcx> {
Ty(Ty<'tcx>),
Const(Const<'tcx>),
@ -946,7 +926,7 @@ impl<'tcx> Term<'tcx> {
/// Form #2 eventually yields one of these `ProjectionPredicate`
/// instances to normalize the LHS.
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct ProjectionPredicate<'tcx> {
pub projection_ty: ProjectionTy<'tcx>,
pub term: Term<'tcx>,
@ -1090,7 +1070,7 @@ impl<'tcx> Predicate<'tcx> {
/// `[[], [U:Bar<T>]]`. Now if there were some particular reference
/// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[],
/// [usize:Bar<isize>]]`.
#[derive(Clone, Debug, TypeFoldable)]
#[derive(Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct InstantiatedPredicates<'tcx> {
pub predicates: Vec<Predicate<'tcx>>,
pub spans: Vec<Span>,
@ -1106,24 +1086,14 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
}
}
#[derive(
Copy,
Clone,
Debug,
PartialEq,
Eq,
HashStable,
TyEncodable,
TyDecodable,
TypeFoldable,
Lift
)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, TyEncodable, TyDecodable, Lift)]
#[derive(TypeFoldable, TypeVisitable)]
pub struct OpaqueTypeKey<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
}
#[derive(Copy, Clone, Debug, TypeFoldable, HashStable, TyEncodable, TyDecodable)]
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, HashStable, TyEncodable, TyDecodable)]
pub struct OpaqueHiddenType<'tcx> {
/// The span of this particular definition of the opaque type. So
/// for example:
@ -1259,7 +1229,7 @@ pub type PlaceholderConst<'tcx> = Placeholder<BoundConst<'tcx>>;
/// except that instead of a `Ty` we bundle the `DefId` of the const parameter.
/// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some`
/// to get the type of `did`.
#[derive(Copy, Clone, Debug, TypeFoldable, Lift, TyEncodable, TyDecodable)]
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
#[derive(Hash, HashStable)]
pub struct WithOptConstParam<T> {
@ -1415,7 +1385,9 @@ impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> {
self.constness().try_fold_with(folder)?,
))
}
}
impl<'tcx> TypeVisitable<'tcx> for ParamEnv<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.caller_bounds().visit_with(visitor)?;
self.reveal().visit_with(visitor)?;
@ -1542,7 +1514,7 @@ impl<'tcx> ParamEnv<'tcx> {
/// `where Box<u32>: Copy`, which are clearly never
/// satisfiable. We generally want to behave as if they were true,
/// although the surrounding function is never reachable.
pub fn and<T: TypeFoldable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
pub fn and<T: TypeVisitable<'tcx>>(self, value: T) -> ParamEnvAnd<'tcx, T> {
match self.reveal() {
Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
@ -1575,7 +1547,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
pub struct ParamEnvAnd<'tcx, T> {
pub param_env: ParamEnv<'tcx>,
pub value: T,

View File

@ -2,7 +2,7 @@ use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar
use crate::ty::subst::{GenericArg, GenericArgKind, Subst};
use crate::ty::{
self, ConstInt, DefIdTree, ParamConst, ScalarInt, Term, Ty, TyCtxt, TypeFoldable,
TypeSuperFoldable,
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable,
};
use rustc_apfloat::ieee::{Double, Single};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
@ -2277,14 +2277,14 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
where
T: TypeFoldable<'tcx>,
T: TypeVisitable<'tcx>,
{
struct LateBoundRegionNameCollector<'a, 'tcx> {
used_region_names: &'a mut FxHashSet<Symbol>,
type_collector: SsoHashSet<Ty<'tcx>>,
}
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
impl<'tcx> ty::visit::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
type BreakTy = ();
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
@ -2388,7 +2388,7 @@ macro_rules! define_print_and_forward_display {
/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
/// the trait path. That is, it will print `Trait<U>` instead of
/// `<T as Trait<U>>`.
#[derive(Copy, Clone, TypeFoldable, Lift)]
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
@ -2400,7 +2400,7 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
/// Wrapper type for `ty::TraitRef` which opts-in to pretty printing only
/// the trait name. That is, it will print `Trait` instead of
/// `<T as Trait<U>>`.
#[derive(Copy, Clone, TypeFoldable, Lift)]
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
pub struct TraitRefPrintOnlyTraitName<'tcx>(ty::TraitRef<'tcx>);
impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitName<'tcx> {
@ -2425,7 +2425,7 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> {
}
}
#[derive(Copy, Clone, TypeFoldable, Lift)]
#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>);
impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> {

View File

@ -345,7 +345,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
}
}
#[derive(Copy, Debug, Clone, TypeFoldable)]
#[derive(Copy, Debug, Clone, TypeFoldable, TypeVisitable)]
struct GeneratorWitness<'tcx>(&'tcx ty::List<Ty<'tcx>>);
impl<'tcx> Relate<'tcx> for GeneratorWitness<'tcx> {

View File

@ -4,8 +4,9 @@
use crate::mir::interpret;
use crate::mir::ProjectionKind;
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable, TypeVisitor};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer};
use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
use crate::ty::{self, InferConst, Lift, Term, Ty, TyCtxt};
use rustc_data_structures::functor::IdFunctor;
use rustc_hir as hir;
@ -183,7 +184,7 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
// For things that don't carry any arena-allocated data (and are
// copy...), just add them to this list.
TrivialTypeFoldableAndLiftImpls! {
TrivialTypeTraversalAndLiftImpls! {
(),
bool,
usize,
@ -452,7 +453,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::PredicateKind<'a> {
impl<'a, 'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<'a, T>
where
<T as Lift<'tcx>>::Lifted: TypeFoldable<'tcx>,
<T as Lift<'tcx>>::Lifted: TypeVisitable<'tcx>,
{
type Lifted = ty::Binder<'tcx, T::Lifted>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
@ -651,7 +652,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::AdtDef<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
Ok(self)
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::AdtDef<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
@ -664,7 +667,9 @@ impl<'tcx, T: TypeFoldable<'tcx>, U: TypeFoldable<'tcx>> TypeFoldable<'tcx> for
) -> Result<(T, U), F::Error> {
Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
}
}
impl<'tcx, T: TypeVisitable<'tcx>, U: TypeVisitable<'tcx>> TypeVisitable<'tcx> for (T, U) {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.0.visit_with(visitor)?;
self.1.visit_with(visitor)
@ -684,7 +689,11 @@ impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>>
self.2.try_fold_with(folder)?,
))
}
}
impl<'tcx, A: TypeVisitable<'tcx>, B: TypeVisitable<'tcx>, C: TypeVisitable<'tcx>>
TypeVisitable<'tcx> for (A, B, C)
{
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.0.visit_with(visitor)?;
self.1.visit_with(visitor)?;
@ -692,19 +701,31 @@ impl<'tcx, A: TypeFoldable<'tcx>, B: TypeFoldable<'tcx>, C: TypeFoldable<'tcx>>
}
}
EnumTypeFoldableImpl! {
EnumTypeTraversalImpl! {
impl<'tcx, T> TypeFoldable<'tcx> for Option<T> {
(Some)(a),
(None),
} where T: TypeFoldable<'tcx>
}
EnumTypeTraversalImpl! {
impl<'tcx, T> TypeVisitable<'tcx> for Option<T> {
(Some)(a),
(None),
} where T: TypeVisitable<'tcx>
}
EnumTypeFoldableImpl! {
EnumTypeTraversalImpl! {
impl<'tcx, T, E> TypeFoldable<'tcx> for Result<T, E> {
(Ok)(a),
(Err)(a),
} where T: TypeFoldable<'tcx>, E: TypeFoldable<'tcx>,
}
EnumTypeTraversalImpl! {
impl<'tcx, T, E> TypeVisitable<'tcx> for Result<T, E> {
(Ok)(a),
(Err)(a),
} where T: TypeVisitable<'tcx>, E: TypeVisitable<'tcx>,
}
impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(
@ -744,7 +765,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
Ok(Rc::from_raw(Rc::into_raw(unique).cast()))
}
}
}
impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Rc<T> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
(**self).visit_with(visitor)
}
@ -788,7 +811,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Arc<T> {
Ok(Arc::from_raw(Arc::into_raw(unique).cast()))
}
}
}
impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Arc<T> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
(**self).visit_with(visitor)
}
@ -798,7 +823,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.try_map_id(|value| value.try_fold_with(folder))
}
}
impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<T> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
(**self).visit_with(visitor)
}
@ -808,7 +835,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.try_map_id(|t| t.try_fold_with(folder))
}
}
impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Vec<T> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
@ -818,7 +847,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<[T]> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.try_map_id(|t| t.try_fold_with(folder))
}
}
impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for Box<[T]> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
@ -828,7 +859,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::EarlyBinder<T> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.try_map_bound(|ty| ty.try_fold_with(folder))
}
}
impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for ty::EarlyBinder<T> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.as_ref().0.visit_with(visitor)
}
@ -838,7 +871,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<'tcx, T> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_binder(self)
}
}
impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for ty::Binder<'tcx, T> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_binder(self)
}
@ -851,7 +886,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeSuperFoldable<'tcx> for ty::Binder<'tcx, T
) -> Result<Self, F::Error> {
self.try_map_bound(|ty| ty.try_fold_with(folder))
}
}
impl<'tcx, T: TypeVisitable<'tcx>> TypeSuperVisitable<'tcx> for ty::Binder<'tcx, T> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.as_ref().skip_binder().visit_with(visitor)
}
@ -861,7 +898,11 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Binder<'tcx, ty::Existentia
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v))
}
}
impl<'tcx> TypeVisitable<'tcx>
for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>
{
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|p| p.visit_with(visitor))
}
@ -871,7 +912,9 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ProjectionKind> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_projs(v))
}
}
impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<ProjectionKind> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
@ -903,7 +946,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
},
})
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::instance::Instance<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
use crate::ty::InstanceDef::*;
self.substs.visit_with(visitor)?;
@ -929,7 +974,9 @@ impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
Ok(Self { instance: self.instance.try_fold_with(folder)?, promoted: self.promoted })
}
}
impl<'tcx> TypeVisitable<'tcx> for interpret::GlobalId<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.instance.visit_with(visitor)
}
@ -939,7 +986,9 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_ty(self)
}
}
impl<'tcx> TypeVisitable<'tcx> for Ty<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_ty(*self)
}
@ -989,7 +1038,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for Ty<'tcx> {
Ok(if *self.kind() == kind { self } else { folder.tcx().mk_ty(kind) })
}
}
impl<'tcx> TypeSuperVisitable<'tcx> for Ty<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match self.kind() {
ty::RawPtr(ref tm) => tm.visit_with(visitor),
@ -1037,7 +1088,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Region<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_region(self)
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::Region<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_region(*self)
}
@ -1050,7 +1103,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Region<'tcx> {
) -> Result<Self, F::Error> {
Ok(self)
}
}
impl<'tcx> TypeSuperVisitable<'tcx> for ty::Region<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
@ -1060,7 +1115,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_predicate(self)
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::Predicate<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_predicate(*self)
}
@ -1082,7 +1139,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Predicate<'tcx> {
let new = self.kind().try_fold_with(folder)?;
Ok(folder.tcx().reuse_or_mk_predicate(self, new))
}
}
impl<'tcx> TypeSuperVisitable<'tcx> for ty::Predicate<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.kind().visit_with(visitor)
}
@ -1092,7 +1151,9 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
ty::util::fold_list(self, folder, |tcx, v| tcx.intern_predicates(v))
}
}
impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<ty::Predicate<'tcx>> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|p| p.visit_with(visitor))
}
@ -1102,7 +1163,9 @@ impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T>
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
self.try_map_id(|x| x.try_fold_with(folder))
}
}
impl<'tcx, T: TypeVisitable<'tcx>, I: Idx> TypeVisitable<'tcx> for IndexVec<I, T> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
@ -1112,7 +1175,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_const(self)
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::Const<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_const(*self)
}
@ -1131,7 +1196,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Const<'tcx> {
Ok(self)
}
}
}
impl<'tcx> TypeSuperVisitable<'tcx> for ty::Const<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.ty().visit_with(visitor)?;
self.kind().visit_with(visitor)
@ -1150,7 +1217,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ConstKind<'tcx> {
| ty::ConstKind::Error(_) => self,
})
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::ConstKind<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match *self {
ty::ConstKind::Infer(ic) => ic.visit_with(visitor),
@ -1168,7 +1237,9 @@ impl<'tcx> TypeFoldable<'tcx> for InferConst<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
Ok(self)
}
}
impl<'tcx> TypeVisitable<'tcx> for InferConst<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}
@ -1178,7 +1249,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
folder.try_fold_unevaluated(self)
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
visitor.visit_unevaluated(*self)
}
@ -1195,7 +1268,9 @@ impl<'tcx> TypeSuperFoldable<'tcx> for ty::Unevaluated<'tcx> {
promoted: self.promoted,
})
}
}
impl<'tcx> TypeSuperVisitable<'tcx> for ty::Unevaluated<'tcx> {
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.substs.visit_with(visitor)
}
@ -1205,7 +1280,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
Ok(self.expand().try_fold_with(folder)?.shrink())
}
}
impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx, ()> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.expand().visit_with(visitor)
}
@ -1215,7 +1292,9 @@ impl<'tcx> TypeFoldable<'tcx> for hir::Constness {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
Ok(self)
}
}
impl<'tcx> TypeVisitable<'tcx> for hir::Constness {
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
ControlFlow::CONTINUE
}

View File

@ -3,11 +3,11 @@
#![allow(rustc::usage_of_ty_tykind)]
use crate::infer::canonical::Canonical;
use crate::ty::fold::ValidateBoundVars;
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
use crate::ty::visit::ValidateBoundVars;
use crate::ty::InferTy::*;
use crate::ty::{
self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeSuperFoldable,
self, AdtDef, DefIdTree, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
TypeVisitor,
};
use crate::ty::{List, ParamEnv};
@ -38,7 +38,7 @@ pub type TyKind<'tcx> = IrTyKind<TyCtxt<'tcx>>;
pub type RegionKind<'tcx> = IrRegionKind<TyCtxt<'tcx>>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, Lift)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct TypeAndMut<'tcx> {
pub ty: Ty<'tcx>,
pub mutbl: hir::Mutability,
@ -201,7 +201,7 @@ static_assert_size!(TyKind<'_>, 32);
/// * `GR`: The "return type", which is the type of value returned upon
/// completion of the generator.
/// * `GW`: The "generator witness".
#[derive(Copy, Clone, Debug, TypeFoldable)]
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct ClosureSubsts<'tcx> {
/// Lifetime and type parameters from the enclosing function,
/// concatenated with a tuple containing the types of the upvars.
@ -328,7 +328,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
}
/// Similar to `ClosureSubsts`; see the above documentation for more.
#[derive(Copy, Clone, Debug, TypeFoldable)]
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct GeneratorSubsts<'tcx> {
pub substs: SubstsRef<'tcx>,
}
@ -608,7 +608,7 @@ impl<'tcx> UpvarSubsts<'tcx> {
/// type of the constant. The reason that `R` is represented as an extra type parameter
/// is the same reason that [`ClosureSubsts`] have `CS` and `U` as type parameters:
/// inline const can reference lifetimes that are internal to the creating function.
#[derive(Copy, Clone, Debug, TypeFoldable)]
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct InlineConstSubsts<'tcx> {
/// Generic parameters from the enclosing item,
/// concatenated with the inferred type of the constant.
@ -655,7 +655,7 @@ impl<'tcx> InlineConstSubsts<'tcx> {
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub enum ExistentialPredicate<'tcx> {
/// E.g., `Iterator`.
Trait(ExistentialTraitRef<'tcx>),
@ -781,7 +781,7 @@ impl<'tcx> List<ty::Binder<'tcx, ExistentialPredicate<'tcx>>> {
/// Trait references also appear in object types like `Foo<U>`, but in
/// that case the `Self` parameter is absent from the substitutions.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct TraitRef<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
@ -853,7 +853,7 @@ impl<'tcx> PolyTraitRef<'tcx> {
/// The substitutions don't include the erased `Self`, only trait
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct ExistentialTraitRef<'tcx> {
pub def_id: DefId,
pub substs: SubstsRef<'tcx>,
@ -986,7 +986,7 @@ pub struct Binder<'tcx, T>(T, &'tcx List<BoundVariableKind>);
impl<'tcx, T> Binder<'tcx, T>
where
T: TypeFoldable<'tcx>,
T: TypeVisitable<'tcx>,
{
/// Wraps `value` in a binder, asserting that `value` does not
/// contain any bound vars that would be bound by the
@ -1050,14 +1050,14 @@ impl<'tcx, T> Binder<'tcx, T> {
Binder(value, self.1)
}
pub fn map_bound_ref<F, U: TypeFoldable<'tcx>>(&self, f: F) -> Binder<'tcx, U>
pub fn map_bound_ref<F, U: TypeVisitable<'tcx>>(&self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(&T) -> U,
{
self.as_ref().map_bound(f)
}
pub fn map_bound<F, U: TypeFoldable<'tcx>>(self, f: F) -> Binder<'tcx, U>
pub fn map_bound<F, U: TypeVisitable<'tcx>>(self, f: F) -> Binder<'tcx, U>
where
F: FnOnce(T) -> U,
{
@ -1069,7 +1069,7 @@ impl<'tcx, T> Binder<'tcx, T> {
Binder(value, self.1)
}
pub fn try_map_bound<F, U: TypeFoldable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E>
pub fn try_map_bound<F, U: TypeVisitable<'tcx>, E>(self, f: F) -> Result<Binder<'tcx, U>, E>
where
F: FnOnce(T) -> Result<U, E>,
{
@ -1092,7 +1092,7 @@ impl<'tcx, T> Binder<'tcx, T> {
/// in `bind`. This may be (debug) asserted in the future.
pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U>
where
U: TypeFoldable<'tcx>,
U: TypeVisitable<'tcx>,
{
if cfg!(debug_assertions) {
let mut validator = ValidateBoundVars::new(self.bound_vars());
@ -1113,7 +1113,7 @@ impl<'tcx, T> Binder<'tcx, T> {
/// would not be that useful.)
pub fn no_bound_vars(self) -> Option<T>
where
T: TypeFoldable<'tcx>,
T: TypeVisitable<'tcx>,
{
if self.0.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
}
@ -1143,7 +1143,7 @@ impl<'tcx, T> Binder<'tcx, Option<T>> {
/// Represents the projection of an associated type. In explicit UFCS
/// form this would be written `<T as Trait<..>>::N`.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct ProjectionTy<'tcx> {
/// The parameters of the associated item.
pub substs: SubstsRef<'tcx>,
@ -1192,7 +1192,7 @@ impl<'tcx> ProjectionTy<'tcx> {
}
}
#[derive(Copy, Clone, Debug, TypeFoldable)]
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
pub struct GenSig<'tcx> {
pub resume_ty: Ty<'tcx>,
pub yield_ty: Ty<'tcx>,
@ -1208,7 +1208,7 @@ pub type PolyGenSig<'tcx> = Binder<'tcx, GenSig<'tcx>>;
/// - `output`: is the return type.
/// - `c_variadic`: indicates whether this is a C-variadic function.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct FnSig<'tcx> {
pub inputs_and_output: &'tcx List<Ty<'tcx>>,
pub c_variadic: bool,
@ -1385,7 +1385,7 @@ impl From<BoundVar> for BoundTy {
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable)]
#[derive(HashStable, TypeFoldable, TypeVisitable)]
pub struct ExistentialProjection<'tcx> {
pub item_def_id: DefId,
pub substs: SubstsRef<'tcx>,

View File

@ -2,10 +2,9 @@
use crate::mir;
use crate::ty::codec::{TyDecoder, TyEncoder};
use crate::ty::fold::{
FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitor,
};
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable};
use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts};
use crate::ty::visit::{TypeVisitable, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
use rustc_data_structures::intern::{Interned, WithStableHash};
@ -205,7 +204,9 @@ impl<'tcx> TypeFoldable<'tcx> for GenericArg<'tcx> {
GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
}
}
}
impl<'tcx> TypeVisitable<'tcx> for GenericArg<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match self.unpack() {
GenericArgKind::Lifetime(lt) => lt.visit_with(visitor),
@ -449,7 +450,9 @@ impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> {
_ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_substs(v)),
}
}
}
impl<'tcx> TypeVisitable<'tcx> for SubstsRef<'tcx> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
@ -485,7 +488,9 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
_ => ty::util::fold_list(self, folder, |tcx, v| tcx.intern_type_list(v)),
}
}
}
impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<Ty<'tcx>> {
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
self.iter().try_for_each(|t| t.visit_with(visitor))
}
@ -722,7 +727,7 @@ impl<'a, 'tcx> SubstFolder<'a, 'tcx> {
/// Stores the user-given substs to reach some fully qualified path
/// (e.g., `<T>::Item` or `<T as Trait>::Item`).
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, Lift)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct UserSubsts<'tcx> {
/// The substitutions for the item as given by the user.
pub substs: SubstsRef<'tcx>,
@ -749,7 +754,7 @@ pub struct UserSubsts<'tcx> {
/// the self type, giving `Foo<?A>`. Finally, we unify that with
/// the self type here, which contains `?A` to be `&'static u32`
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, TypeFoldable, Lift)]
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct UserSelfTy<'tcx> {
pub impl_def_id: DefId,
pub self_ty: Ty<'tcx>,

View File

@ -1,6 +1,6 @@
use crate::traits::specialization_graph;
use crate::ty::fast_reject::{self, SimplifiedType, TreatParams};
use crate::ty::fold::TypeFoldable;
use crate::ty::visit::TypeVisitable;
use crate::ty::{Ident, Ty, TyCtxt};
use hir::def_id::LOCAL_CRATE;
use rustc_hir as hir;

View File

@ -6,6 +6,7 @@ use crate::ty::query::TyCtxtAt;
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
use crate::ty::{
self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitable,
};
use rustc_apfloat::Float as _;
use rustc_ast as ast;

View File

@ -0,0 +1,745 @@
//! A visiting traversal mechanism for complex data structures that contain type
//! information.
//!
//! This is a read-only traversal of the data structure.
//!
//! This traversal has limited flexibility. Only a small number of "types of
//! interest" within the complex data structures can receive custom
//! visitation. These are the ones containing the most important type-related
//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
//!
//! There are three groups of traits involved in each traversal.
//! - `TypeVisitable`. This is implemented once for many types, including:
//! - Types of interest, for which the the methods delegate to the
//! visitor.
//! - All other types, including generic containers like `Vec` and `Option`.
//! It defines a "skeleton" of how they should be visited.
//! - `TypeSuperVisitable`. This is implemented only for each type of interest,
//! and defines the visiting "skeleton" for these types.
//! - `TypeVisitor`. This is implemented for each visitor. This defines how
//! types of interest are visited.
//!
//! This means each visit is a mixture of (a) generic visiting operations, and (b)
//! custom visit operations that are specific to the visitor.
//! - The `TypeVisitable` impls handle most of the traversal, and call into
//! `TypeVisitor` when they encounter a type of interest.
//! - A `TypeVisitor` may call into another `TypeVisitable` impl, because some of
//! the types of interest are recursive and can contain other types of interest.
//! - A `TypeVisitor` may also call into a `TypeSuperVisitable` impl, because each
//! visitor might provide custom handling only for some types of interest, or
//! only for some variants of each type of interest, and then use default
//! traversal for the remaining cases.
//!
//! For example, if you have `struct S(Ty, U)` where `S: TypeVisitable` and `U:
//! TypeVisitable`, and an instance `s = S(ty, u)`, it would be visited like so:
//! ```text
//! s.visit_with(visitor) calls
//! - ty.visit_with(visitor) calls
//! - visitor.visit_ty(ty) may call
//! - ty.super_visit_with(visitor)
//! - u.visit_with(visitor)
//! ```
use crate::mir;
use crate::ty::{self, flags::FlagComputation, Binder, Ty, TyCtxt, TypeFlags};
use rustc_errors::ErrorGuaranteed;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sso::SsoHashSet;
use std::fmt;
use std::ops::ControlFlow;
/// This trait is implemented for every type that can be visited,
/// providing the skeleton of the traversal.
///
/// To implement this conveniently, use the derive macro located in
/// `rustc_macros`.
pub trait TypeVisitable<'tcx>: fmt::Debug + Clone {
/// The entry point for visiting. To visit a value `t` with a visitor `v`
/// call: `t.visit_with(v)`.
///
/// For most types, this just traverses the value, calling `visit_with` on
/// each field/element.
///
/// For types of interest (such as `Ty`), the implementation of this method
/// that calls a visitor method specifically for that type (such as
/// `V::visit_ty`). This is where control transfers from `TypeFoldable` to
/// `TypeVisitor`.
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
/// Returns `true` if `self` has any late-bound regions that are either
/// bound by `binder` or bound by some binder outside of `binder`.
/// If `binder` is `ty::INNERMOST`, this indicates whether
/// there are any late-bound regions that appear free.
fn has_vars_bound_at_or_above(&self, binder: ty::DebruijnIndex) -> bool {
self.visit_with(&mut HasEscapingVarsVisitor { outer_index: binder }).is_break()
}
/// Returns `true` if this `self` has any regions that escape `binder` (and
/// hence are not bound by it).
fn has_vars_bound_above(&self, binder: ty::DebruijnIndex) -> bool {
self.has_vars_bound_at_or_above(binder.shifted_in(1))
}
fn has_escaping_bound_vars(&self) -> bool {
self.has_vars_bound_at_or_above(ty::INNERMOST)
}
#[instrument(level = "trace")]
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
}
fn has_projections(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_PROJECTION)
}
fn has_opaque_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_OPAQUE)
}
fn references_error(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_ERROR)
}
fn error_reported(&self) -> Option<ErrorGuaranteed> {
if self.references_error() {
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
} else {
None
}
}
fn has_param_types_or_consts(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
}
fn has_infer_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_INFER)
}
fn has_infer_types(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER)
}
fn has_infer_types_or_consts(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER)
}
fn needs_infer(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_INFER)
}
fn has_placeholders(&self) -> bool {
self.has_type_flags(
TypeFlags::HAS_RE_PLACEHOLDER
| TypeFlags::HAS_TY_PLACEHOLDER
| TypeFlags::HAS_CT_PLACEHOLDER,
)
}
fn needs_subst(&self) -> bool {
self.has_type_flags(TypeFlags::NEEDS_SUBST)
}
/// "Free" regions in this context means that it has any region
/// that is not (a) erased or (b) late-bound.
fn has_free_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
}
fn has_erased_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_ERASED)
}
/// True if there are any un-erased free regions.
fn has_erasable_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
}
/// Indicates whether this value references only 'global'
/// generic parameters that are the same regardless of what fn we are
/// in. This is used for caching.
fn is_global(&self) -> bool {
!self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
}
/// True if there are any late-bound regions
fn has_late_bound_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
}
/// Indicates whether this value still has parameters/placeholders/inference variables
/// which could be replaced later, in a way that would change the results of `impl`
/// specialization.
fn still_further_specializable(&self) -> bool {
self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE)
}
}
pub trait TypeSuperVisitable<'tcx>: TypeVisitable<'tcx> {
/// Provides a default visit for a type of interest. This should only be
/// called within `TypeVisitor` methods, when a non-custom traversal is
/// desired for the value of the type of interest passed to that method.
/// For example, in `MyVisitor::visit_ty(ty)`, it is valid to call
/// `ty.super_visit_with(self)`, but any other visiting should be done
/// with `xyz.visit_with(self)`.
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>;
}
/// This trait is implemented for every visiting traversal. There is a visit
/// method defined for every type of interest. Each such method has a default
/// that recurses into the type's fields in a non-custom fashion.
pub trait TypeVisitor<'tcx>: Sized {
type BreakTy = !;
fn visit_binder<T: TypeVisitable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
t.super_visit_with(self)
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
t.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
r.super_visit_with(self)
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
c.super_visit_with(self)
}
fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
uv.super_visit_with(self)
}
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
p.super_visit_with(self)
}
fn visit_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> ControlFlow<Self::BreakTy> {
c.super_visit_with(self)
}
}
///////////////////////////////////////////////////////////////////////////
// Region folder
impl<'tcx> TyCtxt<'tcx> {
/// Invoke `callback` on every region appearing free in `value`.
pub fn for_each_free_region(
self,
value: &impl TypeVisitable<'tcx>,
mut callback: impl FnMut(ty::Region<'tcx>),
) {
self.any_free_region_meets(value, |r| {
callback(r);
false
});
}
/// Returns `true` if `callback` returns true for every region appearing free in `value`.
pub fn all_free_regions_meet(
self,
value: &impl TypeVisitable<'tcx>,
mut callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
!self.any_free_region_meets(value, |r| !callback(r))
}
/// Returns `true` if `callback` returns true for some region appearing free in `value`.
pub fn any_free_region_meets(
self,
value: &impl TypeVisitable<'tcx>,
callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
struct RegionVisitor<F> {
/// The index of a binder *just outside* the things we have
/// traversed. If we encounter a bound region bound by this
/// binder or one outer to it, it appears free. Example:
///
/// ```ignore (illustrative)
/// for<'a> fn(for<'b> fn(), T)
/// // ^ ^ ^ ^
/// // | | | | here, would be shifted in 1
/// // | | | here, would be shifted in 2
/// // | | here, would be `INNERMOST` shifted in by 1
/// // | here, initially, binder would be `INNERMOST`
/// ```
///
/// You see that, initially, *any* bound value is free,
/// because we've not traversed any binders. As we pass
/// through a binder, we shift the `outer_index` by 1 to
/// account for the new binder that encloses us.
outer_index: ty::DebruijnIndex,
callback: F,
}
impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
where
F: FnMut(ty::Region<'tcx>) -> bool,
{
type BreakTy = ();
fn visit_binder<T: TypeVisitable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.outer_index.shift_in(1);
let result = t.super_visit_with(self);
self.outer_index.shift_out(1);
result
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match *r {
ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => {
ControlFlow::CONTINUE
}
_ => {
if (self.callback)(r) {
ControlFlow::BREAK
} else {
ControlFlow::CONTINUE
}
}
}
}
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
// We're only interested in types involving regions
if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
ty.super_visit_with(self)
} else {
ControlFlow::CONTINUE
}
}
}
value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }).is_break()
}
/// 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
/// variables will also be equated.
pub fn collect_constrained_late_bound_regions<T>(
self,
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
T: TypeVisitable<'tcx>,
{
self.collect_late_bound_regions(value, true)
}
/// Returns a set of all late-bound regions that appear in `value` anywhere.
pub fn collect_referenced_late_bound_regions<T>(
self,
value: &Binder<'tcx, T>,
) -> FxHashSet<ty::BoundRegionKind>
where
T: TypeVisitable<'tcx>,
{
self.collect_late_bound_regions(value, false)
}
fn collect_late_bound_regions<T>(
self,
value: &Binder<'tcx, T>,
just_constraint: bool,
) -> FxHashSet<ty::BoundRegionKind>
where
T: TypeVisitable<'tcx>,
{
let mut collector = LateBoundRegionsCollector::new(just_constraint);
let result = value.as_ref().skip_binder().visit_with(&mut collector);
assert!(result.is_continue()); // should never have stopped early
collector.regions
}
}
pub struct ValidateBoundVars<'tcx> {
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
binder_index: ty::DebruijnIndex,
// We may encounter the same variable at different levels of binding, so
// this can't just be `Ty`
visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
}
impl<'tcx> ValidateBoundVars<'tcx> {
pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self {
ValidateBoundVars {
bound_vars,
binder_index: ty::INNERMOST,
visited: SsoHashSet::default(),
}
}
}
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
type BreakTy = ();
fn visit_binder<T: TypeVisitable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.binder_index.shift_in(1);
let result = t.super_visit_with(self);
self.binder_index.shift_out(1);
result
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if t.outer_exclusive_binder() < self.binder_index
|| !self.visited.insert((self.binder_index, t))
{
return ControlFlow::BREAK;
}
match *t.kind() {
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
if self.bound_vars.len() <= bound_ty.var.as_usize() {
bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
}
let list_var = self.bound_vars[bound_ty.var.as_usize()];
match list_var {
ty::BoundVariableKind::Ty(kind) => {
if kind != bound_ty.kind {
bug!(
"Mismatched type kinds: {:?} doesn't var in list {:?}",
bound_ty.kind,
list_var
);
}
}
_ => {
bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var)
}
}
}
_ => (),
};
t.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match *r {
ty::ReLateBound(index, br) if index == self.binder_index => {
if self.bound_vars.len() <= br.var.as_usize() {
bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars);
}
let list_var = self.bound_vars[br.var.as_usize()];
match list_var {
ty::BoundVariableKind::Region(kind) => {
if kind != br.kind {
bug!(
"Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})",
br.kind,
list_var,
self.bound_vars
);
}
}
_ => bug!(
"Mismatched bound variable kinds! Expected region, found {:?}",
list_var
),
}
}
_ => (),
};
r.super_visit_with(self)
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
struct FoundEscapingVars;
/// An "escaping var" is a bound var whose binder is not part of `t`. A bound var can be a
/// bound region or a bound type.
///
/// So, for example, consider a type like the following, which has two binders:
///
/// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize))
/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope
/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope
///
/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the
/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
/// fn type*, that type has an escaping region: `'a`.
///
/// Note that what I'm calling an "escaping var" is often just called a "free var". However,
/// we already use the term "free var". It refers to the regions or types that we use to represent
/// bound regions or type params on a fn definition while we are type checking its body.
///
/// To clarify, conceptually there is no particular difference between
/// an "escaping" var and a "free" var. However, there is a big
/// difference in practice. Basically, when "entering" a binding
/// level, one is generally required to do some sort of processing to
/// a bound var, such as replacing it with a fresh/placeholder
/// var, or making an entry in the environment to represent the
/// scope to which it is attached, etc. An escaping var represents
/// a bound var for which this processing has not yet been done.
struct HasEscapingVarsVisitor {
/// Anything bound by `outer_index` or "above" is escaping.
outer_index: ty::DebruijnIndex,
}
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars;
fn visit_binder<T: TypeVisitable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.outer_index.shift_in(1);
let result = t.super_visit_with(self);
self.outer_index.shift_out(1);
result
}
#[inline]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
// If the outer-exclusive-binder is *strictly greater* than
// `outer_index`, that means that `t` contains some content
// bound at `outer_index` or above (because
// `outer_exclusive_binder` is always 1 higher than the
// content in `t`). Therefore, `t` has some escaping vars.
if t.outer_exclusive_binder() > self.outer_index {
ControlFlow::Break(FoundEscapingVars)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
// If the region is bound by `outer_index` or anything outside
// of outer index, then it escapes the binders we have
// visited.
if r.bound_at_or_above_binder(self.outer_index) {
ControlFlow::Break(FoundEscapingVars)
} else {
ControlFlow::CONTINUE
}
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
// we don't have a `visit_infer_const` callback, so we have to
// hook in here to catch this case (annoying...), but
// otherwise we do want to remember to visit the rest of the
// const, as it has types/regions embedded in a lot of other
// places.
match ct.kind() {
ty::ConstKind::Bound(debruijn, _) if debruijn >= self.outer_index => {
ControlFlow::Break(FoundEscapingVars)
}
_ => ct.super_visit_with(self),
}
}
#[inline]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
if predicate.outer_exclusive_binder() > self.outer_index {
ControlFlow::Break(FoundEscapingVars)
} else {
ControlFlow::CONTINUE
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
struct FoundFlags;
// FIXME: Optimize for checking for infer flags
struct HasTypeFlagsVisitor {
flags: ty::TypeFlags,
}
impl std::fmt::Debug for HasTypeFlagsVisitor {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.flags.fmt(fmt)
}
}
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
#[inline]
#[instrument(skip(self), level = "trace")]
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = t.flags();
trace!(t.flags=?t.flags());
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(skip(self), level = "trace")]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = r.type_flags();
trace!(r.flags=?flags);
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(level = "trace")]
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = FlagComputation::for_const(c);
trace!(r.flags=?flags);
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(level = "trace")]
fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
let flags = FlagComputation::for_unevaluated_const(uv);
trace!(r.flags=?flags);
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(level = "trace")]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!(
"HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
predicate,
predicate.flags(),
self.flags
);
if predicate.flags().intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
ControlFlow::CONTINUE
}
}
}
/// Collects all the late-bound regions at the innermost binding level
/// into a hash set.
struct LateBoundRegionsCollector {
current_index: ty::DebruijnIndex,
regions: FxHashSet<ty::BoundRegionKind>,
/// `true` if we only want regions that are known to be
/// "constrained" when you equate this type with another type. In
/// particular, if you have e.g., `&'a u32` and `&'b u32`, equating
/// them constraints `'a == 'b`. But if you have `<&'a u32 as
/// Trait>::Foo` and `<&'b u32 as Trait>::Foo`, normalizing those
/// types may mean that `'a` and `'b` don't appear in the results,
/// so they are not considered *constrained*.
just_constrained: bool,
}
impl LateBoundRegionsCollector {
fn new(just_constrained: bool) -> Self {
LateBoundRegionsCollector {
current_index: ty::INNERMOST,
regions: Default::default(),
just_constrained,
}
}
}
impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
fn visit_binder<T: TypeVisitable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
self.current_index.shift_in(1);
let result = t.super_visit_with(self);
self.current_index.shift_out(1);
result
}
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
// if we are only looking for "constrained" region, we have to
// ignore the inputs to a projection, as they may not appear
// in the normalized form
if self.just_constrained {
if let ty::Projection(..) = t.kind() {
return ControlFlow::CONTINUE;
}
}
t.super_visit_with(self)
}
fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
// if we are only looking for "constrained" region, we have to
// ignore the inputs of an unevaluated const, as they may not appear
// in the normalized form
if self.just_constrained {
if let ty::ConstKind::Unevaluated(..) = c.kind() {
return ControlFlow::CONTINUE;
}
}
c.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ReLateBound(debruijn, br) = *r {
if debruijn == self.current_index {
self.regions.insert(br.kind);
}
}
ControlFlow::CONTINUE
}
}
/// Finds the max universe present
pub struct MaxUniverse {
max_universe: ty::UniverseIndex,
}
impl MaxUniverse {
pub fn new() -> Self {
MaxUniverse { max_universe: ty::UniverseIndex::ROOT }
}
pub fn max_universe(self) -> ty::UniverseIndex {
self.max_universe
}
}
impl<'tcx> TypeVisitor<'tcx> for MaxUniverse {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Placeholder(placeholder) = t.kind() {
self.max_universe = ty::UniverseIndex::from_u32(
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
);
}
t.super_visit_with(self)
}
fn visit_const(&mut self, c: ty::consts::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ConstKind::Placeholder(placeholder) = c.kind() {
self.max_universe = ty::UniverseIndex::from_u32(
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
);
}
c.super_visit_with(self)
}
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::RePlaceholder(placeholder) = *r {
self.max_universe = ty::UniverseIndex::from_u32(
self.max_universe.as_u32().max(placeholder.universe.as_u32()),
);
}
ControlFlow::CONTINUE
}
}

View File

@ -20,7 +20,7 @@ use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::*;
use rustc_middle::thir::{BindingMode, Expr, ExprId, LintLevel, LocalVarId, PatKind, Thir};
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeckResults};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable, TypeckResults};
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_span::Symbol;

View File

@ -19,7 +19,7 @@ use rustc_middle::mir::{
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{
self, ConstKind, EarlyBinder, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable,
self, ConstKind, EarlyBinder, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable,
};
use rustc_span::{def_id::DefId, Span};
use rustc_target::abi::{HasDataLayout, Size, TargetDataLayout};

View File

@ -18,7 +18,8 @@ use rustc_middle::mir::{
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{
self, ConstInt, ConstKind, EarlyBinder, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable,
self, ConstInt, ConstKind, EarlyBinder, Instance, ParamEnv, ScalarInt, Ty, TyCtxt,
TypeVisitable,
};
use rustc_session::lint;
use rustc_span::{def_id::DefId, Span};

View File

@ -2,7 +2,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::mir::TerminatorKind;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::TypeVisitable;
use rustc_middle::ty::{self, subst::SubstsRef, InstanceDef, TyCtxt};
use rustc_session::Limit;

View File

@ -28,7 +28,7 @@ use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::Visitor as _;
use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPass, MirPhase, Promoted};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
use rustc_span::{Span, Symbol};
#[macro_use]

View File

@ -194,7 +194,9 @@ use rustc_middle::mir::{self, Local, Location};
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::{self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, VtblEntry};
use rustc_middle::ty::{
self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitable, VtblEntry,
};
use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext};
use rustc_session::config::EntryFnType;
use rustc_session::lint::builtin::LARGE_ASSIGNMENTS;

View File

@ -9,7 +9,7 @@ use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, Linkage, Visibility};
use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
use rustc_middle::ty::print::characteristic_def_id_of_type;
use rustc_middle::ty::{self, fold::TypeFoldable, DefIdTree, InstanceDef, TyCtxt};
use rustc_middle::ty::{self, visit::TypeVisitable, DefIdTree, InstanceDef, TyCtxt};
use rustc_span::symbol::Symbol;
use super::PartitioningCx;

View File

@ -13,9 +13,9 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::{
self,
fold::{TypeFoldable, TypeSuperFoldable, TypeVisitor},
query::Providers,
subst::SubstsRef,
visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
Const, Ty, TyCtxt,
};
use rustc_span::symbol::sym;

View File

@ -27,7 +27,7 @@ use rustc_middle::thir::abstract_const::Node as ACNode;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Const, DefIdTree, GenericParamDefKind};
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable, TypeVisitor};
use rustc_middle::ty::{TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::hygiene::Transparency;
use rustc_span::symbol::{kw, Ident};
@ -80,7 +80,7 @@ trait DefIdVisitor<'tcx> {
dummy: Default::default(),
}
}
fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> ControlFlow<Self::BreakTy> {
fn visit(&mut self, ty_fragment: impl TypeVisitable<'tcx>) -> ControlFlow<Self::BreakTy> {
ty_fragment.visit_with(&mut self.skeleton())
}
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<Self::BreakTy> {

Some files were not shown because too many files have changed in this diff Show More