derive TypeVisitable and TypeFoldable for mir types
This commit is contained in:
parent
d376012a43
commit
a5ab8da1e2
5 changed files with 25 additions and 312 deletions
|
@ -2028,6 +2028,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||||
/// particular, one must be wary of `NaN`!
|
/// particular, one must be wary of `NaN`!
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||||
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
pub struct Constant<'tcx> {
|
pub struct Constant<'tcx> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
||||||
|
|
|
@ -488,7 +488,7 @@ pub struct CopyNonOverlapping<'tcx> {
|
||||||
/// must also be `cleanup`. This is a part of the type system and checked statically, so it is
|
/// must also be `cleanup`. This is a part of the type system and checked statically, so it is
|
||||||
/// still an error to have such an edge in the CFG even if it's known that it won't be taken at
|
/// still an error to have such an edge in the CFG even if it's known that it won't be taken at
|
||||||
/// runtime.
|
/// runtime.
|
||||||
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
|
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
|
||||||
pub enum TerminatorKind<'tcx> {
|
pub enum TerminatorKind<'tcx> {
|
||||||
/// Block has one successor; we continue execution there.
|
/// Block has one successor; we continue execution there.
|
||||||
Goto { target: BasicBlock },
|
Goto { target: BasicBlock },
|
||||||
|
@ -741,7 +741,7 @@ pub enum TerminatorKind<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information about an assertion failure.
|
/// Information about an assertion failure.
|
||||||
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
|
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
|
||||||
pub enum AssertKind<O> {
|
pub enum AssertKind<O> {
|
||||||
BoundsCheck { len: O, index: O },
|
BoundsCheck { len: O, index: O },
|
||||||
Overflow(BinOp, O, O),
|
Overflow(BinOp, O, O),
|
||||||
|
@ -863,7 +863,7 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
|
||||||
///
|
///
|
||||||
/// Rust currently requires that every place obey those two rules. This is checked by MIRI and taken
|
/// Rust currently requires that every place obey those two rules. This is checked by MIRI and taken
|
||||||
/// advantage of by codegen (via `gep inbounds`). That is possibly subject to change.
|
/// advantage of by codegen (via `gep inbounds`). That is possibly subject to change.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
pub struct Place<'tcx> {
|
pub struct Place<'tcx> {
|
||||||
pub local: Local,
|
pub local: Local,
|
||||||
|
|
||||||
|
@ -955,7 +955,7 @@ pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
|
||||||
/// **Needs clarifiation:** Is loading a place that has its variant index set well-formed? Miri
|
/// **Needs clarifiation:** Is loading a place that has its variant index set well-formed? Miri
|
||||||
/// currently implements it, but it seems like this may be something to check against in the
|
/// currently implements it, but it seems like this may be something to check against in the
|
||||||
/// validator.
|
/// validator.
|
||||||
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
pub enum Operand<'tcx> {
|
pub enum Operand<'tcx> {
|
||||||
/// Creates a value by loading the given place.
|
/// Creates a value by loading the given place.
|
||||||
///
|
///
|
||||||
|
@ -986,7 +986,7 @@ pub enum Operand<'tcx> {
|
||||||
/// Computing any rvalue begins by evaluating the places and operands in some order (**Needs
|
/// Computing any rvalue begins by evaluating the places and operands in some order (**Needs
|
||||||
/// clarification**: Which order?). These are then used to produce a "value" - the same kind of
|
/// clarification**: Which order?). These are then used to produce a "value" - the same kind of
|
||||||
/// value that an [`Operand`] produces.
|
/// value that an [`Operand`] produces.
|
||||||
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
|
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
|
||||||
pub enum Rvalue<'tcx> {
|
pub enum Rvalue<'tcx> {
|
||||||
/// Yields the operand unchanged
|
/// Yields the operand unchanged
|
||||||
Use(Operand<'tcx>),
|
Use(Operand<'tcx>),
|
||||||
|
@ -1146,6 +1146,7 @@ pub enum CastKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||||
|
#[derive(TypeFoldable, TypeVisitable)]
|
||||||
pub enum AggregateKind<'tcx> {
|
pub enum AggregateKind<'tcx> {
|
||||||
/// The type is of the element
|
/// The type is of the element
|
||||||
Array(Ty<'tcx>),
|
Array(Ty<'tcx>),
|
||||||
|
|
|
@ -102,7 +102,7 @@ impl<'a> Iterator for SwitchTargetsIter<'a> {
|
||||||
|
|
||||||
impl<'a> ExactSizeIterator for SwitchTargetsIter<'a> {}
|
impl<'a> ExactSizeIterator for SwitchTargetsIter<'a> {}
|
||||||
|
|
||||||
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
|
#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
|
||||||
pub struct Terminator<'tcx> {
|
pub struct Terminator<'tcx> {
|
||||||
pub source_info: SourceInfo,
|
pub source_info: SourceInfo,
|
||||||
pub kind: TerminatorKind<'tcx>,
|
pub kind: TerminatorKind<'tcx>,
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
//! `TypeFoldable` implementations for MIR types
|
//! `TypeFoldable` implementations for MIR types
|
||||||
|
|
||||||
|
use rustc_ast::InlineAsmTemplatePiece;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::ty;
|
use crate::ty;
|
||||||
use rustc_data_structures::functor::IdFunctor;
|
|
||||||
|
|
||||||
TrivialTypeTraversalAndLiftImpls! {
|
TrivialTypeTraversalAndLiftImpls! {
|
||||||
BlockTailInfo,
|
BlockTailInfo,
|
||||||
|
@ -13,96 +14,27 @@ TrivialTypeTraversalAndLiftImpls! {
|
||||||
SourceScope,
|
SourceScope,
|
||||||
SourceScopeLocalData,
|
SourceScopeLocalData,
|
||||||
UserTypeAnnotationIndex,
|
UserTypeAnnotationIndex,
|
||||||
|
BorrowKind,
|
||||||
|
CastKind,
|
||||||
|
BinOp,
|
||||||
|
NullOp,
|
||||||
|
UnOp,
|
||||||
|
hir::Movability,
|
||||||
|
BasicBlock,
|
||||||
|
SwitchTargets,
|
||||||
|
GeneratorKind,
|
||||||
|
GeneratorSavedLocal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
|
impl<'tcx> TypeFoldable<'tcx> for &'tcx [InlineAsmTemplatePiece] {
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
|
||||||
use crate::mir::TerminatorKind::*;
|
|
||||||
|
|
||||||
let kind = match self.kind {
|
|
||||||
Goto { target } => Goto { target },
|
|
||||||
SwitchInt { discr, switch_ty, targets } => SwitchInt {
|
|
||||||
discr: discr.try_fold_with(folder)?,
|
|
||||||
switch_ty: switch_ty.try_fold_with(folder)?,
|
|
||||||
targets,
|
|
||||||
},
|
|
||||||
Drop { place, target, unwind } => {
|
|
||||||
Drop { place: place.try_fold_with(folder)?, target, unwind }
|
|
||||||
}
|
|
||||||
DropAndReplace { place, value, target, unwind } => DropAndReplace {
|
|
||||||
place: place.try_fold_with(folder)?,
|
|
||||||
value: value.try_fold_with(folder)?,
|
|
||||||
target,
|
|
||||||
unwind,
|
|
||||||
},
|
|
||||||
Yield { value, resume, resume_arg, drop } => Yield {
|
|
||||||
value: value.try_fold_with(folder)?,
|
|
||||||
resume,
|
|
||||||
resume_arg: resume_arg.try_fold_with(folder)?,
|
|
||||||
drop,
|
|
||||||
},
|
|
||||||
Call { func, args, destination, target, cleanup, from_hir_call, fn_span } => Call {
|
|
||||||
func: func.try_fold_with(folder)?,
|
|
||||||
args: args.try_fold_with(folder)?,
|
|
||||||
destination: destination.try_fold_with(folder)?,
|
|
||||||
target,
|
|
||||||
cleanup,
|
|
||||||
from_hir_call,
|
|
||||||
fn_span,
|
|
||||||
},
|
|
||||||
Assert { cond, expected, msg, target, cleanup } => {
|
|
||||||
use AssertKind::*;
|
|
||||||
let msg = match msg {
|
|
||||||
BoundsCheck { len, index } => BoundsCheck {
|
|
||||||
len: len.try_fold_with(folder)?,
|
|
||||||
index: index.try_fold_with(folder)?,
|
|
||||||
},
|
|
||||||
Overflow(op, l, r) => {
|
|
||||||
Overflow(op, l.try_fold_with(folder)?, r.try_fold_with(folder)?)
|
|
||||||
}
|
|
||||||
OverflowNeg(op) => OverflowNeg(op.try_fold_with(folder)?),
|
|
||||||
DivisionByZero(op) => DivisionByZero(op.try_fold_with(folder)?),
|
|
||||||
RemainderByZero(op) => RemainderByZero(op.try_fold_with(folder)?),
|
|
||||||
ResumedAfterReturn(_) | ResumedAfterPanic(_) => msg,
|
|
||||||
};
|
|
||||||
Assert { cond: cond.try_fold_with(folder)?, expected, msg, target, cleanup }
|
|
||||||
}
|
|
||||||
GeneratorDrop => GeneratorDrop,
|
|
||||||
Resume => Resume,
|
|
||||||
Abort => Abort,
|
|
||||||
Return => Return,
|
|
||||||
Unreachable => Unreachable,
|
|
||||||
FalseEdge { real_target, imaginary_target } => {
|
|
||||||
FalseEdge { real_target, imaginary_target }
|
|
||||||
}
|
|
||||||
FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
|
|
||||||
InlineAsm { template, operands, options, line_spans, destination, cleanup } => {
|
|
||||||
InlineAsm {
|
|
||||||
template,
|
|
||||||
operands: operands.try_fold_with(folder)?,
|
|
||||||
options,
|
|
||||||
line_spans,
|
|
||||||
destination,
|
|
||||||
cleanup,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ok(Terminator { source_info: self.source_info, kind })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for GeneratorKind {
|
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
|
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
|
impl<'tcx> TypeFoldable<'tcx> for &'tcx [Span] {
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
|
||||||
Ok(Place {
|
Ok(self)
|
||||||
local: self.local.try_fold_with(folder)?,
|
|
||||||
projection: self.projection.try_fold_with(folder)?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,91 +44,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
|
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
|
||||||
use crate::mir::Rvalue::*;
|
|
||||||
Ok(match self {
|
|
||||||
Use(op) => Use(op.try_fold_with(folder)?),
|
|
||||||
Repeat(op, len) => Repeat(op.try_fold_with(folder)?, len.try_fold_with(folder)?),
|
|
||||||
ThreadLocalRef(did) => ThreadLocalRef(did.try_fold_with(folder)?),
|
|
||||||
Ref(region, bk, place) => {
|
|
||||||
Ref(region.try_fold_with(folder)?, bk, place.try_fold_with(folder)?)
|
|
||||||
}
|
|
||||||
CopyForDeref(place) => CopyForDeref(place.try_fold_with(folder)?),
|
|
||||||
AddressOf(mutability, place) => AddressOf(mutability, place.try_fold_with(folder)?),
|
|
||||||
Len(place) => Len(place.try_fold_with(folder)?),
|
|
||||||
Cast(kind, op, ty) => Cast(kind, op.try_fold_with(folder)?, ty.try_fold_with(folder)?),
|
|
||||||
BinaryOp(op, box (rhs, lhs)) => {
|
|
||||||
BinaryOp(op, Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)))
|
|
||||||
}
|
|
||||||
CheckedBinaryOp(op, box (rhs, lhs)) => CheckedBinaryOp(
|
|
||||||
op,
|
|
||||||
Box::new((rhs.try_fold_with(folder)?, lhs.try_fold_with(folder)?)),
|
|
||||||
),
|
|
||||||
UnaryOp(op, val) => UnaryOp(op, val.try_fold_with(folder)?),
|
|
||||||
Discriminant(place) => Discriminant(place.try_fold_with(folder)?),
|
|
||||||
NullaryOp(op, ty) => NullaryOp(op, ty.try_fold_with(folder)?),
|
|
||||||
Aggregate(kind, fields) => {
|
|
||||||
let kind = kind.try_map_id(|kind| {
|
|
||||||
Ok(match kind {
|
|
||||||
AggregateKind::Array(ty) => AggregateKind::Array(ty.try_fold_with(folder)?),
|
|
||||||
AggregateKind::Tuple => AggregateKind::Tuple,
|
|
||||||
AggregateKind::Adt(def, v, substs, user_ty, n) => AggregateKind::Adt(
|
|
||||||
def,
|
|
||||||
v,
|
|
||||||
substs.try_fold_with(folder)?,
|
|
||||||
user_ty.try_fold_with(folder)?,
|
|
||||||
n,
|
|
||||||
),
|
|
||||||
AggregateKind::Closure(id, substs) => {
|
|
||||||
AggregateKind::Closure(id, substs.try_fold_with(folder)?)
|
|
||||||
}
|
|
||||||
AggregateKind::Generator(id, substs, movablity) => {
|
|
||||||
AggregateKind::Generator(id, substs.try_fold_with(folder)?, movablity)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})?;
|
|
||||||
Aggregate(kind, fields.try_fold_with(folder)?)
|
|
||||||
}
|
|
||||||
ShallowInitBox(op, ty) => {
|
|
||||||
ShallowInitBox(op.try_fold_with(folder)?, ty.try_fold_with(folder)?)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
|
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
|
||||||
Ok(match self {
|
|
||||||
Operand::Copy(place) => Operand::Copy(place.try_fold_with(folder)?),
|
|
||||||
Operand::Move(place) => Operand::Move(place.try_fold_with(folder)?),
|
|
||||||
Operand::Constant(c) => Operand::Constant(c.try_fold_with(folder)?),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for GeneratorSavedLocal {
|
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
|
|
||||||
Ok(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
|
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> {
|
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
|
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
|
||||||
Ok(Constant {
|
|
||||||
span: self.span,
|
|
||||||
user_ty: self.user_ty.try_fold_with(folder)?,
|
|
||||||
literal: self.literal.try_fold_with(folder)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
|
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||||
|
|
|
@ -3,159 +3,17 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::ty;
|
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>> {
|
impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
|
||||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
self.iter().try_for_each(|t| t.visit_with(visitor))
|
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),
|
|
||||||
CopyForDeref(ref place) => {
|
|
||||||
let op = &Operand::Copy(*place);
|
|
||||||
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 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> {
|
impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
|
||||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
ControlFlow::CONTINUE
|
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> {
|
impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> {
|
||||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||||
visitor.visit_mir_const(*self)
|
visitor.visit_mir_const(*self)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue