From a5ab8da1e22c2cbfca30209ef30cd469a913f08a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 15 Sep 2022 14:42:43 +0000 Subject: [PATCH] derive TypeVisitable and TypeFoldable for mir types --- compiler/rustc_middle/src/mir/mod.rs | 1 + compiler/rustc_middle/src/mir/syntax.rs | 11 +- compiler/rustc_middle/src/mir/terminator.rs | 2 +- .../rustc_middle/src/mir/type_foldable.rs | 181 ++---------------- .../rustc_middle/src/mir/type_visitable.rs | 142 -------------- 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 { BoundsCheck { len: O, index: O }, Overflow(BinOp, O, O), @@ -863,7 +863,7 @@ pub type AssertMessage<'tcx> = AssertKind>; /// /// 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>; /// **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>(self, folder: &mut F) -> Result { - 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>(self, _: &mut F) -> Result { +impl<'tcx> TypeFoldable<'tcx> for &'tcx [InlineAsmTemplatePiece] { + fn try_fold_with>(self, _folder: &mut F) -> Result { Ok(self) } } -impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { - fn try_fold_with>(self, folder: &mut F) -> Result { - 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>(self, _folder: &mut F) -> Result { + Ok(self) } } @@ -112,91 +44,12 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { } } -impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { - fn try_fold_with>(self, folder: &mut F) -> Result { - 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>(self, folder: &mut F) -> Result { - 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>(self, _: &mut F) -> Result { - Ok(self) - } -} - impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix { fn try_fold_with>(self, _: &mut F) -> Result { Ok(self) } } -impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> { - fn try_fold_with>(self, folder: &mut F) -> Result { - 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>(self, folder: &mut F) -> Result { 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>(&self, visitor: &mut V) -> ControlFlow { - 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>(&self, _: &mut V) -> ControlFlow { - ControlFlow::CONTINUE - } -} - -impl<'tcx> TypeVisitable<'tcx> for Place<'tcx> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.local.visit_with(visitor)?; - self.projection.visit_with(visitor) - } -} - impl<'tcx> TypeVisitable<'tcx> for &'tcx ty::List> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.iter().try_for_each(|t| t.visit_with(visitor)) } } - -impl<'tcx> TypeVisitable<'tcx> for Rvalue<'tcx> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - 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>(&self, visitor: &mut V) -> ControlFlow { - 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>(&self, _: &mut V) -> ControlFlow { - ControlFlow::CONTINUE - } -} - impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix { fn visit_with>(&self, _: &mut V) -> ControlFlow { ControlFlow::CONTINUE } } -impl<'tcx> TypeVisitable<'tcx> for Constant<'tcx> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.literal.visit_with(visitor)?; - self.user_ty.visit_with(visitor) - } -} - impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_mir_const(*self)