about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-09-15 14:42:43 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-09-15 14:42:43 +0000
commita5ab8da1e22c2cbfca30209ef30cd469a913f08a (patch)
treeda76dc85e6fbf18ed693d1498a4ddbfd7c8ccc8e
parentd376012a43f91f6dfdd761d786c016f7c343f950 (diff)
downloadrust-a5ab8da1e22c2cbfca30209ef30cd469a913f08a.tar.gz
rust-a5ab8da1e22c2cbfca30209ef30cd469a913f08a.zip
derive TypeVisitable and TypeFoldable for mir types
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs1
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs11
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs2
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs181
-rw-r--r--compiler/rustc_middle/src/mir/type_visitable.rs142
5 files changed, 25 insertions, 312 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 685f11db4e0..af00118fcbe 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -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,
 
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 89b999b55b9..c7d0283aac9 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -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>),
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 02a9958525b..4ea333cff7d 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -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>,
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 64dac2e3834..b8f8f697a9c 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -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> {
diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs
index 7875b2bb8cf..c01b6215c2d 100644
--- a/compiler/rustc_middle/src/mir/type_visitable.rs
+++ b/compiler/rustc_middle/src/mir/type_visitable.rs
@@ -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)