Skip to content

Commit

Permalink
we don't need intern_mode any more
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Oct 14, 2023
1 parent 27de852 commit 2619695
Showing 1 changed file with 5 additions and 84 deletions.
89 changes: 5 additions & 84 deletions compiler/rustc_const_eval/src/interpret/intern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,14 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_ev
/// The ectx from which we intern.
ecx: &'rt mut InterpCx<'mir, 'tcx, M>,
/// Previously encountered safe references.
ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, InternMode)>,
ref_tracking: &'rt mut RefTracking<MPlaceTy<'tcx>>,
/// A list of all encountered allocations. After type-based interning, we traverse this list to
/// also intern allocations that are only referenced by a raw pointer or inside a union.
leftover_allocations: &'rt mut FxIndexSet<AllocId>,
/// The root kind of the value that we're looking at. This field is never mutated for a
/// particular allocation. It is primarily used to make as many allocations as possible
/// read-only so LLVM can place them in const memory.
mode: InternMode,
/// This field stores whether we are *currently* inside an `UnsafeCell`. This can affect
/// the intern mode of references we encounter.
inside_unsafe_cell: bool,
/// The mutability with which to intern the pointers we find.
intern_mutability: Mutability,
}

#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
enum InternMode {
/// A static and its current mutability. Below shared references inside a `static mut`,
/// this is *immutable*, and below mutable references inside an `UnsafeCell`, this
/// is *mutable*.
Static(hir::Mutability),
/// A `const`.
Const,
}

/// Signalling data structure to ensure we don't recurse
/// into the memory of other constants or statics
struct IsStaticOrFn;
Expand Down Expand Up @@ -151,7 +134,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
// Raw pointers (and boxes) are handled by the `leftover_allocations` logic.
let tcx = self.ecx.tcx;
let ty = mplace.layout.ty;
if let ty::Ref(_, referenced_ty, ref_mutability) = *ty.kind() {
if let ty::Ref(_, referenced_ty, _ref_mutability) = *ty.kind() {
let value = self.ecx.read_immediate(mplace)?;
let mplace = self.ecx.ref_to_mplace(&value)?;
assert_eq!(mplace.layout.ty, referenced_ty);
Expand All @@ -174,56 +157,14 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
// Check if we have encountered this pointer+layout combination before.
// Only recurse for allocation-backed pointers.
if let Some(alloc_id) = mplace.ptr().provenance {
// Compute the mode with which we intern this. Our goal here is to make as many
// statics as we can immutable so they can be placed in read-only memory by LLVM.
let ref_mode = match self.mode {
InternMode::Static(mutbl) => {
// In statics, merge outer mutability with reference mutability and
// take into account whether we are in an `UnsafeCell`.

// The only way a mutable reference actually works as a mutable reference is
// by being in a `static mut` directly or behind another mutable reference.
// If there's an immutable reference or we are inside a `static`, then our
// mutable reference is equivalent to an immutable one. As an example:
// `&&mut Foo` is semantically equivalent to `&&Foo`
match ref_mutability {
_ if self.inside_unsafe_cell => {
// Inside an `UnsafeCell` is like inside a `static mut`, the "outer"
// mutability does not matter.
InternMode::Static(ref_mutability)
}
Mutability::Not => {
// A shared reference, things become immutable.
// We do *not* consider `freeze` here: `intern_shallow` considers
// `freeze` for the actual mutability of this allocation; the intern
// mode for references contained in this allocation is tracked more
// precisely when traversing the referenced data (by tracking
// `UnsafeCell`). This makes sure that `&(&i32, &Cell<i32>)` still
// has the left inner reference interned into a read-only
// allocation.
InternMode::Static(Mutability::Not)
}
Mutability::Mut => {
// Mutable reference.
InternMode::Static(mutbl)
}
}
}
InternMode::Const => {
// Ignore `UnsafeCell`, everything is immutable. Validity does some sanity
// checking for mutable references that we encounter -- they must all be
// ZST.
InternMode::Const
}
};
match self.intern_shallow(alloc_id) {
// No need to recurse, these are interned already and statics may have
// cycles, so we don't want to recurse there
Some(IsStaticOrFn) => {}
// intern everything referenced by this value. The mutability is taken from the
// reference. It is checked above that mutable references only happen in
// `static mut`
None => self.ref_tracking.track((mplace, ref_mode), || ()),
None => self.ref_tracking.track(mplace, || ()),
}
}
Ok(())
Expand Down Expand Up @@ -272,19 +213,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
return Ok(());
}

if let Some(def) = mplace.layout.ty.ty_adt_def() {
if def.is_unsafe_cell() {
// We are crossing over an `UnsafeCell`, we can mutate again. This means that
// References we encounter inside here are interned as pointing to mutable
// allocations.
// Remember the `old` value to handle nested `UnsafeCell`.
let old = std::mem::replace(&mut self.inside_unsafe_cell, true);
let walked = self.walk_value(mplace);
self.inside_unsafe_cell = old;
return walked;
}
}

self.walk_value(mplace)
}
}
Expand Down Expand Up @@ -314,11 +242,6 @@ pub fn intern_const_alloc_recursive<
intern_kind: InternKind,
ret: &MPlaceTy<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let base_intern_mode = match intern_kind {
InternKind::Static(mutbl) => InternMode::Static(mutbl),
// `Constant` includes array lengths.
InternKind::Constant | InternKind::Promoted => InternMode::Const,
};
// We are interning recursively, and for mutability we are distinguishing the "root" allocation
// that we are starting in, and all other allocations that we are encountering recursively.
let (base_mutability, inner_mutability) = match intern_kind {
Expand Down Expand Up @@ -363,20 +286,18 @@ pub fn intern_const_alloc_recursive<
base_mutability,
);

ref_tracking.track((ret.clone(), base_intern_mode), || ());
ref_tracking.track(ret.clone(), || ());

// We do a type-based traversal to find more allocations to intern. The interner is currently
// mid-refactoring; eventually the type-based traversal will be replaced but a simple traversal
// of all provenance we see in the allocations, but for now we avoid changing rustc error
// messages or accepting extra programs by keeping the old type-based interner around.
while let Some(((mplace, mode), _)) = ref_tracking.todo.pop() {
while let Some((mplace, _)) = ref_tracking.todo.pop() {
let res = InternVisitor {
ref_tracking: &mut ref_tracking,
ecx,
mode,
leftover_allocations,
intern_mutability: inner_mutability,
inside_unsafe_cell: false,
}
.visit_value(&mplace);
// We deliberately *ignore* interpreter errors here. When there is a problem, the remaining
Expand Down

0 comments on commit 2619695

Please sign in to comment.