summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_smir/src/stable_mir
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_smir/src/stable_mir')
-rw-r--r--compiler/rustc_smir/src/stable_mir/mir/body.rs322
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs28
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs414
3 files changed, 758 insertions, 6 deletions
diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs
index 468e915d1..c16bd6cbd 100644
--- a/compiler/rustc_smir/src/stable_mir/mir/body.rs
+++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs
@@ -1,4 +1,8 @@
-use crate::stable_mir::ty::Ty;
+use crate::rustc_internal::Opaque;
+use crate::stable_mir::ty::{
+ AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region,
+};
+use crate::stable_mir::{self, ty::Ty};
#[derive(Clone, Debug)]
pub struct Body {
@@ -130,18 +134,225 @@ pub enum AsyncGeneratorKind {
Fn,
}
+pub(crate) type LocalDefId = Opaque;
+pub(crate) type CounterValueReference = Opaque;
+pub(crate) type InjectedExpressionId = Opaque;
+pub(crate) type ExpressionOperandId = Opaque;
+
+/// The FakeReadCause describes the type of pattern why a FakeRead statement exists.
+#[derive(Clone, Debug)]
+pub enum FakeReadCause {
+ ForMatchGuard,
+ ForMatchedPlace(LocalDefId),
+ ForGuardBinding,
+ ForLet(LocalDefId),
+ ForIndex,
+}
+
+/// Describes what kind of retag is to be performed
+#[derive(Clone, Debug)]
+pub enum RetagKind {
+ FnEntry,
+ TwoPhase,
+ Raw,
+ Default,
+}
+
+#[derive(Clone, Debug)]
+pub enum Variance {
+ Covariant,
+ Invariant,
+ Contravariant,
+ Bivariant,
+}
+
+#[derive(Clone, Debug)]
+pub enum Op {
+ Subtract,
+ Add,
+}
+
+#[derive(Clone, Debug)]
+pub enum CoverageKind {
+ Counter {
+ function_source_hash: usize,
+ id: CounterValueReference,
+ },
+ Expression {
+ id: InjectedExpressionId,
+ lhs: ExpressionOperandId,
+ op: Op,
+ rhs: ExpressionOperandId,
+ },
+ Unreachable,
+}
+
+#[derive(Clone, Debug)]
+pub struct CodeRegion {
+ pub file_name: String,
+ pub start_line: usize,
+ pub start_col: usize,
+ pub end_line: usize,
+ pub end_col: usize,
+}
+
+#[derive(Clone, Debug)]
+pub struct Coverage {
+ pub kind: CoverageKind,
+ pub code_region: Option<CodeRegion>,
+}
+
+#[derive(Clone, Debug)]
+pub struct CopyNonOverlapping {
+ pub src: Operand,
+ pub dst: Operand,
+ pub count: Operand,
+}
+
+#[derive(Clone, Debug)]
+pub enum NonDivergingIntrinsic {
+ Assume(Operand),
+ CopyNonOverlapping(CopyNonOverlapping),
+}
+
#[derive(Clone, Debug)]
pub enum Statement {
Assign(Place, Rvalue),
+ FakeRead(FakeReadCause, Place),
+ SetDiscriminant { place: Place, variant_index: VariantIdx },
+ Deinit(Place),
+ StorageLive(Local),
+ StorageDead(Local),
+ Retag(RetagKind, Place),
+ PlaceMention(Place),
+ AscribeUserType { place: Place, projections: UserTypeProjection, variance: Variance },
+ Coverage(Coverage),
+ Intrinsic(NonDivergingIntrinsic),
+ ConstEvalCounter,
Nop,
}
-// FIXME this is incomplete
#[derive(Clone, Debug)]
pub enum Rvalue {
- Use(Operand),
+ /// Creates a pointer with the indicated mutability to the place.
+ ///
+ /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like
+ /// `&raw v` or `addr_of!(v)`.
+ AddressOf(Mutability, Place),
+
+ /// Creates an aggregate value, like a tuple or struct.
+ ///
+ /// This is needed because dataflow analysis needs to distinguish
+ /// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo`
+ /// has a destructor.
+ ///
+ /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After
+ /// generator lowering, `Generator` aggregate kinds are disallowed too.
+ Aggregate(AggregateKind, Vec<Operand>),
+
+ /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second
+ /// parameter may be a `usize` as well.
+ /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats,
+ /// raw pointers, or function pointers and return a `bool`. The types of the operands must be
+ /// matching, up to the usual caveat of the lifetimes in function pointers.
+ /// * Left and right shift operations accept signed or unsigned integers not necessarily of the
+ /// same type and return a value of the same type as their LHS. Like in Rust, the RHS is
+ /// truncated as needed.
+ /// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching
+ /// types and return a value of that type.
+ /// * The remaining operations accept signed integers, unsigned integers, or floats with
+ /// matching types and return a value of that type.
+ BinaryOp(BinOp, Operand, Operand),
+
+ /// Performs essentially all of the casts that can be performed via `as`.
+ ///
+ /// This allows for casts from/to a variety of types.
+ Cast(CastKind, Operand, Ty),
+
+ /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
+ ///
+ /// For addition, subtraction, and multiplication on integers the error condition is set when
+ /// the infinite precision result would not be equal to the actual result.
CheckedBinaryOp(BinOp, Operand, Operand),
+
+ /// A CopyForDeref is equivalent to a read from a place.
+ /// When such a read happens, it is guaranteed that the only use of the returned value is a
+ /// deref operation, immediately followed by one or more projections.
+ CopyForDeref(Place),
+
+ /// Computes the discriminant of the place, returning it as an integer of type
+ /// [`discriminant_ty`]. Returns zero for types without discriminant.
+ ///
+ /// The validity requirements for the underlying value are undecided for this rvalue, see
+ /// [#91095]. Note too that the value of the discriminant is not the same thing as the
+ /// variant index; use [`discriminant_for_variant`] to convert.
+ ///
+ /// [`discriminant_ty`]: rustc_middle::ty::Ty::discriminant_ty
+ /// [#91095]: https://github.com/rust-lang/rust/issues/91095
+ /// [`discriminant_for_variant`]: rustc_middle::ty::Ty::discriminant_for_variant
+ Discriminant(Place),
+
+ /// Yields the length of the place, as a `usize`.
+ ///
+ /// If the type of the place is an array, this is the array length. For slices (`[T]`, not
+ /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is
+ /// ill-formed for places of other types.
+ Len(Place),
+
+ /// Creates a reference to the place.
+ Ref(Region, BorrowKind, Place),
+
+ /// Creates an array where each element is the value of the operand.
+ ///
+ /// This is the cause of a bug in the case where the repetition count is zero because the value
+ /// is not dropped, see [#74836].
+ ///
+ /// Corresponds to source code like `[x; 32]`.
+ ///
+ /// [#74836]: https://github.com/rust-lang/rust/issues/74836
+ Repeat(Operand, Const),
+
+ /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
+ ///
+ /// This is different from a normal transmute because dataflow analysis will treat the box as
+ /// initialized but its content as uninitialized. Like other pointer casts, this in general
+ /// affects alias analysis.
+ ShallowInitBox(Operand, Ty),
+
+ /// Creates a pointer/reference to the given thread local.
+ ///
+ /// The yielded type is a `*mut T` if the static is mutable, otherwise if the static is extern a
+ /// `*const T`, and if neither of those apply a `&T`.
+ ///
+ /// **Note:** This is a runtime operation that actually executes code and is in this sense more
+ /// like a function call. Also, eliminating dead stores of this rvalue causes `fn main() {}` to
+ /// SIGILL for some reason that I (JakobDegen) never got a chance to look into.
+ ///
+ /// **Needs clarification**: Are there weird additional semantics here related to the runtime
+ /// nature of this operation?
+ ThreadLocalRef(stable_mir::CrateItem),
+
+ /// Computes a value as described by the operation.
+ NullaryOp(NullOp, Ty),
+
+ /// Exactly like `BinaryOp`, but less operands.
+ ///
+ /// Also does two's-complement arithmetic. Negation requires a signed integer or a float;
+ /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds
+ /// return a value with the same type as their operand.
UnaryOp(UnOp, Operand),
+
+ /// Yields the operand unchanged
+ Use(Operand),
+}
+
+#[derive(Clone, Debug)]
+pub enum AggregateKind {
+ Array(Ty),
+ Tuple,
+ Adt(AdtDef, VariantIdx, GenericArgs, Option<UserTypeAnnotationIndex>, Option<FieldIdx>),
+ Closure(ClosureDef, GenericArgs),
+ Generator(GeneratorDef, GenericArgs, Movability),
}
#[derive(Clone, Debug)]
@@ -153,12 +364,115 @@ pub enum Operand {
#[derive(Clone, Debug)]
pub struct Place {
- pub local: usize,
+ pub local: Local,
pub projection: String,
}
#[derive(Clone, Debug)]
+pub struct UserTypeProjection {
+ pub base: UserTypeAnnotationIndex,
+ pub projection: String,
+}
+
+pub type Local = usize;
+
+type FieldIdx = usize;
+
+/// The source-order index of a variant in a type.
+pub type VariantIdx = usize;
+
+type UserTypeAnnotationIndex = usize;
+
+#[derive(Clone, Debug)]
pub struct SwitchTarget {
pub value: u128,
pub target: usize,
}
+
+#[derive(Clone, Debug)]
+pub enum BorrowKind {
+ /// Data must be immutable and is aliasable.
+ Shared,
+
+ /// The immediately borrowed place must be immutable, but projections from
+ /// it don't need to be. For example, a shallow borrow of `a.b` doesn't
+ /// conflict with a mutable borrow of `a.b.c`.
+ Shallow,
+
+ /// Data is mutable and not aliasable.
+ Mut {
+ /// `true` if this borrow arose from method-call auto-ref
+ kind: MutBorrowKind,
+ },
+}
+
+#[derive(Clone, Debug)]
+pub enum MutBorrowKind {
+ Default,
+ TwoPhaseBorrow,
+ ClosureCapture,
+}
+
+#[derive(Clone, Debug)]
+pub enum Mutability {
+ Not,
+ Mut,
+}
+
+#[derive(Clone, Debug)]
+pub enum Safety {
+ Unsafe,
+ Normal,
+}
+
+#[derive(Clone, Debug)]
+pub enum PointerCoercion {
+ /// Go from a fn-item type to a fn-pointer type.
+ ReifyFnPointer,
+
+ /// Go from a safe fn pointer to an unsafe fn pointer.
+ UnsafeFnPointer,
+
+ /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
+ /// It cannot convert a closure that requires unsafe.
+ ClosureFnPointer(Safety),
+
+ /// Go from a mut raw pointer to a const raw pointer.
+ MutToConstPointer,
+
+ /// Go from `*const [T; N]` to `*const T`
+ ArrayToPointer,
+
+ /// Unsize a pointer/reference value, e.g., `&[T; n]` to
+ /// `&[T]`. Note that the source could be a thin or fat pointer.
+ /// This will do things like convert thin pointers to fat
+ /// pointers, or convert structs containing thin pointers to
+ /// structs containing fat pointers, or convert between fat
+ /// pointers.
+ Unsize,
+}
+
+#[derive(Clone, Debug)]
+pub enum CastKind {
+ PointerExposeAddress,
+ PointerFromExposedAddress,
+ PointerCoercion(PointerCoercion),
+ DynStar,
+ IntToInt,
+ FloatToInt,
+ FloatToFloat,
+ IntToFloat,
+ PtrToPtr,
+ FnPtrToPtr,
+ Transmute,
+}
+
+#[derive(Clone, Debug)]
+pub enum NullOp {
+ /// Returns the size of a value of that type.
+ SizeOf,
+ /// Returns the minimum alignment of a type.
+ AlignOf,
+ /// Returns the offset of a field.
+ OffsetOf(Vec<FieldIdx>),
+}
diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs
index 5e599a77b..19061742b 100644
--- a/compiler/rustc_smir/src/stable_mir/mod.rs
+++ b/compiler/rustc_smir/src/stable_mir/mod.rs
@@ -15,7 +15,7 @@ use std::cell::Cell;
use crate::rustc_smir::Tables;
-use self::ty::{Ty, TyKind};
+use self::ty::{ImplDef, ImplTrait, TraitDecl, TraitDef, Ty, TyKind};
pub mod mir;
pub mod ty;
@@ -32,6 +32,12 @@ pub type DefId = usize;
/// A list of crate items.
pub type CrateItems = Vec<CrateItem>;
+/// A list of trait decls.
+pub type TraitDecls = Vec<TraitDef>;
+
+/// A list of impl trait decls.
+pub type ImplTraitDecls = Vec<ImplDef>;
+
/// Holds information about a crate.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Crate {
@@ -79,11 +85,31 @@ pub fn all_local_items() -> CrateItems {
with(|cx| cx.all_local_items())
}
+pub fn all_trait_decls() -> TraitDecls {
+ with(|cx| cx.all_trait_decls())
+}
+
+pub fn trait_decl(trait_def: &TraitDef) -> TraitDecl {
+ with(|cx| cx.trait_decl(trait_def))
+}
+
+pub fn all_trait_impls() -> ImplTraitDecls {
+ with(|cx| cx.all_trait_impls())
+}
+
+pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
+ with(|cx| cx.trait_impl(trait_impl))
+}
+
pub trait Context {
fn entry_fn(&mut self) -> Option<CrateItem>;
/// Retrieve all items of the local crate that have a MIR associated with them.
fn all_local_items(&mut self) -> CrateItems;
fn mir_body(&mut self, item: &CrateItem) -> mir::Body;
+ fn all_trait_decls(&mut self) -> TraitDecls;
+ fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl;
+ fn all_trait_impls(&mut self) -> ImplTraitDecls;
+ fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait;
/// Get information about the local crate.
fn local_crate(&self) -> Crate;
/// Retrieve a list of all external crates.
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index 3181af46e..7a6601f09 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -1,4 +1,10 @@
-use super::with;
+use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer};
+
+use super::{mir::Mutability, mir::Safety, with, DefId};
+use crate::{
+ rustc_internal::{opaque, Opaque},
+ rustc_smir::{Stable, Tables},
+};
#[derive(Copy, Clone, Debug)]
pub struct Ty(pub usize);
@@ -9,9 +15,21 @@ impl Ty {
}
}
+#[derive(Debug, Clone)]
+pub struct Const {
+ pub literal: ConstantKind,
+}
+
+type Ident = Opaque;
+pub(crate) type Region = Opaque;
+type Span = Opaque;
+
#[derive(Clone, Debug)]
pub enum TyKind {
RigidTy(RigidTy),
+ Alias(AliasKind, AliasTy),
+ Param(ParamTy),
+ Bound(usize, BoundTy),
}
#[derive(Clone, Debug)]
@@ -21,6 +39,19 @@ pub enum RigidTy {
Int(IntTy),
Uint(UintTy),
Float(FloatTy),
+ Adt(AdtDef, GenericArgs),
+ Foreign(ForeignDef),
+ Str,
+ Array(Ty, Const),
+ Slice(Ty),
+ RawPtr(Ty, Mutability),
+ Ref(Region, Ty, Mutability),
+ FnDef(FnDef, GenericArgs),
+ FnPtr(PolyFnSig),
+ Closure(ClosureDef, GenericArgs),
+ Generator(GeneratorDef, GenericArgs, Movability),
+ Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind),
+ Never,
Tuple(Vec<Ty>),
}
@@ -49,3 +80,384 @@ pub enum FloatTy {
F32,
F64,
}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Movability {
+ Static,
+ Movable,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ForeignDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FnDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ClosureDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct GeneratorDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ParamDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct BrNamedDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct AdtDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct AliasDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct TraitDef(pub(crate) DefId);
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ConstDef(pub(crate) DefId);
+
+impl TraitDef {
+ pub fn trait_decl(&self) -> TraitDecl {
+ with(|cx| cx.trait_decl(self))
+ }
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ImplDef(pub(crate) DefId);
+
+impl ImplDef {
+ pub fn trait_impl(&self) -> ImplTrait {
+ with(|cx| cx.trait_impl(self))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct GenericArgs(pub Vec<GenericArgKind>);
+
+#[derive(Clone, Debug)]
+pub enum GenericArgKind {
+ Lifetime(Region),
+ Type(Ty),
+ Const(Const),
+}
+
+#[derive(Clone, Debug)]
+pub enum TermKind {
+ Type(Ty),
+ Const(Const),
+}
+
+#[derive(Clone, Debug)]
+pub enum AliasKind {
+ Projection,
+ Inherent,
+ Opaque,
+ Weak,
+}
+
+#[derive(Clone, Debug)]
+pub struct AliasTy {
+ pub def_id: AliasDef,
+ pub args: GenericArgs,
+}
+
+pub type PolyFnSig = Binder<FnSig>;
+
+#[derive(Clone, Debug)]
+pub struct FnSig {
+ pub inputs_and_output: Vec<Ty>,
+ pub c_variadic: bool,
+ pub unsafety: Safety,
+ pub abi: Abi,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum Abi {
+ Rust,
+ C { unwind: bool },
+ Cdecl { unwind: bool },
+ Stdcall { unwind: bool },
+ Fastcall { unwind: bool },
+ Vectorcall { unwind: bool },
+ Thiscall { unwind: bool },
+ Aapcs { unwind: bool },
+ Win64 { unwind: bool },
+ SysV64 { unwind: bool },
+ PtxKernel,
+ Msp430Interrupt,
+ X86Interrupt,
+ AmdGpuKernel,
+ EfiApi,
+ AvrInterrupt,
+ AvrNonBlockingInterrupt,
+ CCmseNonSecureCall,
+ Wasm,
+ System { unwind: bool },
+ RustIntrinsic,
+ RustCall,
+ PlatformIntrinsic,
+ Unadjusted,
+ RustCold,
+ RiscvInterruptM,
+ RiscvInterruptS,
+}
+
+#[derive(Clone, Debug)]
+pub struct Binder<T> {
+ pub value: T,
+ pub bound_vars: Vec<BoundVariableKind>,
+}
+
+#[derive(Clone, Debug)]
+pub struct EarlyBinder<T> {
+ pub value: T,
+}
+
+#[derive(Clone, Debug)]
+pub enum BoundVariableKind {
+ Ty(BoundTyKind),
+ Region(BoundRegionKind),
+ Const,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum BoundTyKind {
+ Anon,
+ Param(ParamDef, String),
+}
+
+#[derive(Clone, Debug)]
+pub enum BoundRegionKind {
+ BrAnon(Option<Span>),
+ BrNamed(BrNamedDef, String),
+ BrEnv,
+}
+
+#[derive(Clone, Debug)]
+pub enum DynKind {
+ Dyn,
+ DynStar,
+}
+
+#[derive(Clone, Debug)]
+pub enum ExistentialPredicate {
+ Trait(ExistentialTraitRef),
+ Projection(ExistentialProjection),
+ AutoTrait(TraitDef),
+}
+
+#[derive(Clone, Debug)]
+pub struct ExistentialTraitRef {
+ pub def_id: TraitDef,
+ pub generic_args: GenericArgs,
+}
+
+#[derive(Clone, Debug)]
+pub struct ExistentialProjection {
+ pub def_id: TraitDef,
+ pub generic_args: GenericArgs,
+ pub term: TermKind,
+}
+
+#[derive(Clone, Debug)]
+pub struct ParamTy {
+ pub index: u32,
+ pub name: String,
+}
+
+#[derive(Clone, Debug)]
+pub struct BoundTy {
+ pub var: usize,
+ pub kind: BoundTyKind,
+}
+
+pub type Bytes = Vec<Option<u8>>;
+pub type Size = usize;
+pub type Prov = Opaque;
+pub type Align = u64;
+pub type Promoted = u32;
+pub type InitMaskMaterialized = Vec<u64>;
+
+/// Stores the provenance information of pointers stored in memory.
+#[derive(Clone, Debug)]
+pub struct ProvenanceMap {
+ /// Provenance in this map applies from the given offset for an entire pointer-size worth of
+ /// bytes. Two entries in this map are always at least a pointer size apart.
+ pub ptrs: Vec<(Size, Prov)>,
+}
+
+#[derive(Clone, Debug)]
+pub struct Allocation {
+ pub bytes: Bytes,
+ pub provenance: ProvenanceMap,
+ pub align: Align,
+ pub mutability: Mutability,
+}
+
+impl Allocation {
+ /// Creates new empty `Allocation` from given `Align`.
+ fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation {
+ Allocation {
+ bytes: Vec::new(),
+ provenance: ProvenanceMap { ptrs: Vec::new() },
+ align: align.bytes(),
+ mutability: Mutability::Not,
+ }
+ }
+}
+
+// We need this method instead of a Stable implementation
+// because we need to get `Ty` of the const we are trying to create, to do that
+// we need to have access to `ConstantKind` but we can't access that inside Stable impl.
+pub fn new_allocation<'tcx>(
+ const_kind: &rustc_middle::mir::ConstantKind<'tcx>,
+ const_value: ConstValue<'tcx>,
+ tables: &mut Tables<'tcx>,
+) -> Allocation {
+ match const_value {
+ ConstValue::Scalar(scalar) => {
+ let size = scalar.size();
+ let align = tables
+ .tcx
+ .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+ .unwrap()
+ .align;
+ let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi);
+ allocation
+ .write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar)
+ .unwrap();
+ allocation.stable(tables)
+ }
+ ConstValue::ZeroSized => {
+ let align = tables
+ .tcx
+ .layout_of(rustc_middle::ty::ParamEnv::empty().and(const_kind.ty()))
+ .unwrap()
+ .align;
+ Allocation::new_empty_allocation(align.abi)
+ }
+ ConstValue::Slice { data, start, end } => {
+ let alloc_id = tables.tcx.create_memory_alloc(data);
+ let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start));
+ let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx);
+ let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize(
+ (end - start) as u64,
+ &tables.tcx,
+ );
+ let layout = tables
+ .tcx
+ .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+ .unwrap();
+ let mut allocation =
+ rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi);
+ allocation
+ .write_scalar(
+ &tables.tcx,
+ alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size),
+ scalar_ptr,
+ )
+ .unwrap();
+ allocation
+ .write_scalar(
+ &tables.tcx,
+ alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()),
+ scalar_len,
+ )
+ .unwrap();
+ allocation.stable(tables)
+ }
+ ConstValue::ByRef { alloc, offset } => {
+ let ty_size = tables
+ .tcx
+ .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty()))
+ .unwrap()
+ .size;
+ allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables)
+ }
+ }
+}
+
+/// Creates an `Allocation` only from information within the `AllocRange`.
+pub fn allocation_filter<'tcx>(
+ alloc: &rustc_middle::mir::interpret::Allocation,
+ alloc_range: AllocRange,
+ tables: &mut Tables<'tcx>,
+) -> Allocation {
+ let mut bytes: Vec<Option<u8>> = alloc
+ .inspect_with_uninit_and_ptr_outside_interpreter(
+ alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(),
+ )
+ .iter()
+ .copied()
+ .map(Some)
+ .collect();
+ for (i, b) in bytes.iter_mut().enumerate() {
+ if !alloc
+ .init_mask()
+ .get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize()))
+ {
+ *b = None;
+ }
+ }
+ let mut ptrs = Vec::new();
+ for (offset, prov) in alloc
+ .provenance()
+ .ptrs()
+ .iter()
+ .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end())
+ {
+ ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov)));
+ }
+ Allocation {
+ bytes: bytes,
+ provenance: ProvenanceMap { ptrs },
+ align: alloc.align.bytes(),
+ mutability: alloc.mutability.stable(tables),
+ }
+}
+
+#[derive(Clone, Debug)]
+pub enum ConstantKind {
+ Allocated(Allocation),
+ Unevaluated(UnevaluatedConst),
+ ParamCt(Opaque),
+}
+
+#[derive(Clone, Debug)]
+pub struct UnevaluatedConst {
+ pub ty: Ty,
+ pub def: ConstDef,
+ pub args: GenericArgs,
+ pub promoted: Option<Promoted>,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum TraitSpecializationKind {
+ None,
+ Marker,
+ AlwaysApplicable,
+}
+
+#[derive(Clone, Debug)]
+pub struct TraitDecl {
+ pub def_id: TraitDef,
+ pub unsafety: Safety,
+ pub paren_sugar: bool,
+ pub has_auto_impl: bool,
+ pub is_marker: bool,
+ pub is_coinductive: bool,
+ pub skip_array_during_method_dispatch: bool,
+ pub specialization_kind: TraitSpecializationKind,
+ pub must_implement_one_of: Option<Vec<Ident>>,
+ pub implement_via_object: bool,
+ pub deny_explicit_impl: bool,
+}
+
+pub type ImplTrait = EarlyBinder<TraitRef>;
+
+#[derive(Clone, Debug)]
+pub struct TraitRef {
+ pub def_id: TraitDef,
+ pub args: GenericArgs,
+}