derive TypeVisitable and TypeFoldable for mir types
This commit is contained in:
parent
d376012a43
commit
a5ab8da1e2
@ -2028,6 +2028,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
|
||||
/// particular, one must be wary of `NaN`!
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct Constant<'tcx> {
|
||||
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
|
||||
/// still an error to have such an edge in the CFG even if it's known that it won't be taken at
|
||||
/// runtime.
|
||||
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
|
||||
#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
|
||||
pub enum TerminatorKind<'tcx> {
|
||||
/// Block has one successor; we continue execution there.
|
||||
Goto { target: BasicBlock },
|
||||
@ -741,7 +741,7 @@ pub enum TerminatorKind<'tcx> {
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
BoundsCheck { len: O, index: 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
|
||||
/// 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 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
|
||||
/// currently implements it, but it seems like this may be something to check against in the
|
||||
/// validator.
|
||||
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
|
||||
pub enum Operand<'tcx> {
|
||||
/// 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
|
||||
/// clarification**: Which order?). These are then used to produce a "value" - the same kind of
|
||||
/// 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> {
|
||||
/// Yields the operand unchanged
|
||||
Use(Operand<'tcx>),
|
||||
@ -1146,6 +1146,7 @@ pub enum CastKind {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub enum AggregateKind<'tcx> {
|
||||
/// The type is of the element
|
||||
Array(Ty<'tcx>),
|
||||
|
@ -102,7 +102,7 @@ impl<'a> Iterator 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 source_info: SourceInfo,
|
||||
pub kind: TerminatorKind<'tcx>,
|
||||
|
@ -1,8 +1,9 @@
|
||||
//! `TypeFoldable` implementations for MIR types
|
||||
|
||||
use rustc_ast::InlineAsmTemplatePiece;
|
||||
|
||||
use super::*;
|
||||
use crate::ty;
|
||||
use rustc_data_structures::functor::IdFunctor;
|
||||
|
||||
TrivialTypeTraversalAndLiftImpls! {
|
||||
BlockTailInfo,
|
||||
@ -13,96 +14,27 @@ TrivialTypeTraversalAndLiftImpls! {
|
||||
SourceScope,
|
||||
SourceScopeLocalData,
|
||||
UserTypeAnnotationIndex,
|
||||
BorrowKind,
|
||||
CastKind,
|
||||
BinOp,
|
||||
NullOp,
|
||||
UnOp,
|
||||
hir::Movability,
|
||||
BasicBlock,
|
||||
SwitchTargets,
|
||||
GeneratorKind,
|
||||
GeneratorSavedLocal,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
|
||||
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> {
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx [InlineAsmTemplatePiece] {
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(Place {
|
||||
local: self.local.try_fold_with(folder)?,
|
||||
projection: self.projection.try_fold_with(folder)?,
|
||||
})
|
||||
impl<'tcx> TypeFoldable<'tcx> for &'tcx [Span] {
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
|
||||
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> {
|
||||
#[inline(always)]
|
||||
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
|
@ -3,159 +3,17 @@
|
||||
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),
|
||||
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> {
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user