Skip to content

Commit 87a730f

Browse files
authored
Revert "Assert size for interned Value" & Mark Slot trait as unsafe (#915)
* Revert "Assert size for interned `Value`" This reverts commit 793dc41. * Mark `Slot` trait as unsafe
1 parent 8528bab commit 87a730f

File tree

4 files changed

+36
-37
lines changed

4 files changed

+36
-37
lines changed

src/input.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ pub trait HasBuilder {
290290
type Builder;
291291
}
292292

293-
impl<C> Slot for Value<C>
293+
// SAFETY: `Value<C>` is our private type branded over the unique configuration `C`.
294+
unsafe impl<C> Slot for Value<C>
294295
where
295296
C: Configuration,
296297
{

src/interned.rs

Lines changed: 27 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,15 @@ impl<C: Configuration> Default for IngredientShard<C> {
100100

101101
// SAFETY: `LinkedListLink` is `!Sync`, however, the linked list is only accessed through the
102102
// ingredient lock, and values are only ever linked to a single list on the ingredient.
103-
unsafe impl<Fields: Sync> Sync for Value<Fields> {}
103+
unsafe impl<C: Configuration> Sync for Value<C> {}
104104

105-
intrusive_adapter!(ValueAdapter<C> = UnsafeRef<ValueForConfiguration<C>>: ValueForConfiguration<C> { link: LinkedListLink } where C: Configuration);
106-
107-
#[cfg(not(feature = "shuttle"))]
108-
#[cfg(target_pointer_width = "64")]
109-
const _: [(); std::mem::size_of::<Value<()>>()] = [(); std::mem::size_of::<[usize; 7]>()];
110-
111-
#[allow(type_alias_bounds)]
112-
type ValueForConfiguration<C: Configuration> = Value<C::Fields<'static>>;
105+
intrusive_adapter!(ValueAdapter<C> = UnsafeRef<Value<C>>: Value<C> { link: LinkedListLink } where C: Configuration);
113106

114107
/// Struct storing the interned fields.
115-
pub struct Value<Fields> {
108+
pub struct Value<C>
109+
where
110+
C: Configuration,
111+
{
116112
/// The index of the shard containing this value.
117113
shard: u16,
118114

@@ -123,7 +119,7 @@ pub struct Value<Fields> {
123119
///
124120
/// These are valid for read-only access as long as the lock is held
125121
/// or the value has been validated in the current revision.
126-
fields: UnsafeCell<Fields>,
122+
fields: UnsafeCell<C::Fields<'static>>,
127123

128124
/// Memos attached to this interned value.
129125
///
@@ -182,10 +178,13 @@ impl ValueShared {
182178
}
183179
}
184180

185-
impl<Fields> Value<Fields> {
181+
impl<C> Value<C>
182+
where
183+
C: Configuration,
184+
{
186185
/// Fields of this interned struct.
187186
#[cfg(feature = "salsa_unstable")]
188-
pub fn fields(&self) -> &Fields {
187+
pub fn fields(&self) -> &C::Fields<'static> {
189188
// SAFETY: The fact that this function is safe is technically unsound. However, interned
190189
// values are only exposed if they have been validated in the current revision, which
191190
// ensures that they are not reused while being accessed.
@@ -574,9 +573,7 @@ where
574573
.unwrap_or((Durability::MAX, Revision::max()));
575574

576575
// Allocate the value slot.
577-
let id = zalsa_local.allocate(zalsa, self.ingredient_index, |id| ValueForConfiguration::<
578-
C,
579-
> {
576+
let id = zalsa_local.allocate(zalsa, self.ingredient_index, |id| Value::<C> {
580577
shard: shard_index as u16,
581578
link: LinkedListLink::new(),
582579
memos: UnsafeCell::new(MemoTable::default()),
@@ -589,7 +586,7 @@ where
589586
}),
590587
});
591588

592-
let value = Self::table_get(zalsa, id);
589+
let value = zalsa.table().get::<Value<C>>(id);
593590
// SAFETY: We hold the lock for the shard containing the value.
594591
let value_shared = unsafe { &mut *value.shared.get() };
595592

@@ -608,7 +605,7 @@ where
608605
shard.key_map.insert_unique(hash, id, hasher);
609606

610607
debug_assert_eq!(hash, {
611-
let value = Self::table_get(zalsa, id);
608+
let value = zalsa.table().get::<Value<C>>(id);
612609

613610
// SAFETY: We hold the lock for the shard containing the value.
614611
unsafe { self.hasher.hash_one(&*value.fields.get()) }
@@ -687,7 +684,7 @@ where
687684
unsafe fn value_hash<'db>(&'db self, id: Id, zalsa: &'db Zalsa) -> u64 {
688685
// This closure is only called if the table is resized. So while it's expensive
689686
// to lookup all values, it will only happen rarely.
690-
let value = Self::table_get(zalsa, id);
687+
let value = zalsa.table().get::<Value<C>>(id);
691688

692689
// SAFETY: We hold the lock for the shard containing the value.
693690
unsafe { self.hasher.hash_one(&*value.fields.get()) }
@@ -702,12 +699,12 @@ where
702699
id: Id,
703700
key: &Key,
704701
zalsa: &'db Zalsa,
705-
found_value: &Cell<Option<&'db ValueForConfiguration<C>>>,
702+
found_value: &Cell<Option<&'db Value<C>>>,
706703
) -> bool
707704
where
708705
C::Fields<'db>: HashEqLike<Key>,
709706
{
710-
let value = Self::table_get(zalsa, id);
707+
let value = zalsa.table().get::<Value<C>>(id);
711708
found_value.set(Some(value));
712709

713710
// SAFETY: We hold the lock for the shard containing the value.
@@ -725,7 +722,7 @@ where
725722
/// Lookup the data for an interned value based on its ID.
726723
pub fn data<'db>(&'db self, db: &'db dyn Database, id: Id) -> &'db C::Fields<'db> {
727724
let zalsa = db.zalsa();
728-
let value = Self::table_get(zalsa, id);
725+
let value = zalsa.table().get::<Value<C>>(id);
729726

730727
debug_assert!(
731728
{
@@ -767,16 +764,8 @@ where
767764
pub fn entries<'db>(
768765
&'db self,
769766
db: &'db dyn crate::Database,
770-
) -> impl Iterator<Item = &'db ValueForConfiguration<C>> {
771-
db.zalsa().table().slots_of::<ValueForConfiguration<C>>()
772-
}
773-
774-
#[inline]
775-
fn table_get(zalsa: &Zalsa, id: Id) -> &ValueForConfiguration<C>
776-
where
777-
C: Configuration,
778-
{
779-
zalsa.table().get::<ValueForConfiguration<C>>(id)
767+
) -> impl Iterator<Item = &'db Value<C>> {
768+
db.zalsa().table().slots_of::<Value<C>>()
780769
}
781770
}
782771

@@ -805,7 +794,7 @@ where
805794
let current_revision = zalsa.current_revision();
806795
self.revision_queue.record(current_revision);
807796

808-
let value = zalsa.table().get::<ValueForConfiguration<C>>(input);
797+
let value = zalsa.table().get::<Value<C>>(input);
809798

810799
// SAFETY: `value.shard` is guaranteed to be in-bounds for `self.shards`.
811800
let _shard = unsafe { self.shards.get_unchecked(value.shard as usize) }.lock();
@@ -854,7 +843,11 @@ where
854843
}
855844
}
856845

857-
impl<Fields: Send + Sync + 'static> Slot for Value<Fields> {
846+
// SAFETY: `Value<C>` is our private type branded over the unique configuration `C`.
847+
unsafe impl<C> Slot for Value<C>
848+
where
849+
C: Configuration,
850+
{
858851
#[inline(always)]
859852
unsafe fn memos(&self, _current_revision: Revision) -> &MemoTable {
860853
// SAFETY: The fact that we have a reference to the `Value` means it must

src/table.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,11 @@ pub struct Table {
3030
non_full_pages: Mutex<FxHashMap<IngredientIndex, Vec<PageIndex>>>,
3131
}
3232

33-
pub(crate) trait Slot: Any + Send + Sync {
33+
/// # Safety
34+
///
35+
/// Implementors of this trait need to make sure that their type is unique with respect to
36+
/// their owning ingredient as the allocation strategy relies on this.
37+
pub(crate) unsafe trait Slot: Any + Send + Sync {
3438
/// Access the [`MemoTable`][] for this slot.
3539
///
3640
/// # Safety condition

src/tracked_struct.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,8 @@ where
912912
}
913913
}
914914

915-
impl<C> Slot for Value<C>
915+
// SAFETY: `Value<C>` is our private type branded over the unique configuration `C`.
916+
unsafe impl<C> Slot for Value<C>
916917
where
917918
C: Configuration,
918919
{

0 commit comments

Comments
 (0)