Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
/// - A constant
/// - A static
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
#[derive(HashStable, Lift)]
#[derive(HashStable, Lift, TypeFoldable, TypeVisitable)]
pub struct GlobalId<'tcx> {
/// For a constant or static, the `Instance` of the item itself.
/// For a promoted global, the `Instance` of the function they belong to.
Expand Down
20 changes: 2 additions & 18 deletions compiler/rustc_middle/src/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_apfloat::{
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};

use crate::ty::{Lift, ParamEnv, ScalarInt, Ty, TyCtxt};
use crate::ty::{ParamEnv, ScalarInt, Ty, TyCtxt};

use super::{
AllocId, AllocRange, ConstAllocation, InterpResult, Pointer, PointerArithmetic, Provenance,
Expand All @@ -27,7 +27,7 @@ pub struct ConstAlloc<'tcx> {
/// Represents a constant value in Rust. `Scalar` and `Slice` are optimizations for
/// array length computations, enum discriminants and the pattern matching logic.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)]
#[derive(HashStable)]
#[derive(HashStable, Lift)]
pub enum ConstValue<'tcx> {
/// Used only for types with `layout::abi::Scalar` ABI.
///
Expand All @@ -53,22 +53,6 @@ pub enum ConstValue<'tcx> {
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(ConstValue<'_>, 32);

impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
type Lifted = ConstValue<'tcx>;
fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<ConstValue<'tcx>> {
Some(match self {
ConstValue::Scalar(s) => ConstValue::Scalar(s),
ConstValue::ZeroSized => ConstValue::ZeroSized,
ConstValue::Slice { data, start, end } => {
ConstValue::Slice { data: tcx.lift(data)?, start, end }
}
ConstValue::ByRef { alloc, offset } => {
ConstValue::ByRef { alloc: tcx.lift(alloc)?, offset }
}
})
}
}

impl<'tcx> ConstValue<'tcx> {
#[inline]
pub fn try_to_scalar(&self) -> Option<Scalar<AllocId>> {
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down Expand Up @@ -2551,8 +2552,6 @@ impl UserTypeProjection {
}
}

TrivialTypeTraversalAndLiftImpls! { ProjectionKind, }

impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
Ok(UserTypeProjection {
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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,

Expand All @@ -872,7 +872,7 @@ pub struct Place<'tcx> {
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(TyEncodable, TyDecodable, HashStable)]
#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
pub enum ProjectionElem<V, T> {
Deref,
Field(Field, T),
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -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>),
Expand Down Expand Up @@ -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>),
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down
204 changes: 17 additions & 187 deletions compiler/rustc_middle/src/mir/type_foldable.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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)
}
}

Expand All @@ -112,114 +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 PlaceElem<'tcx> {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
use crate::mir::ProjectionElem::*;

Ok(match self {
Deref => Deref,
Field(f, ty) => Field(f, ty.try_fold_with(folder)?),
Index(v) => Index(v.try_fold_with(folder)?),
Downcast(symbol, variantidx) => Downcast(symbol, variantidx),
ConstantIndex { offset, min_length, from_end } => {
ConstantIndex { offset, min_length, from_end }
}
Subslice { from, to, from_end } => Subslice { from, to, from_end },
})
}
}

impl<'tcx> TypeFoldable<'tcx> for Field {
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _: &mut F) -> Result<Self, F::Error> {
Ok(self)
}
}

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> {
Expand Down
Loading