Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

derive various impls instead of hand-rolling them #101858

Merged
merged 6 commits into from
Sep 15, 2022
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