Skip to main content

midenc_hir/ir/
entity.rs

1mod adapter;
2mod group;
3mod list;
4mod map;
5mod storage;
6
7use core::{
8    alloc::{AllocError, Layout},
9    any::Any,
10    cell::{Cell, UnsafeCell},
11    fmt,
12    hash::Hash,
13    mem::MaybeUninit,
14    ops::{Deref, DerefMut},
15    ptr::NonNull,
16};
17
18pub use self::{
19    group::EntityGroup,
20    list::{
21        EntityList, EntityListCursor, EntityListCursorMut, EntityListItem, EntityListIter,
22        MaybeDefaultEntityListIter,
23    },
24    map::{
25        EntityMap, EntityMapCursor, EntityMapCursorMut, EntityMapItem, EntityMapIter,
26        EntityWithKey, MaybeDefaultEntityMapIter,
27    },
28    storage::{EntityRange, EntityRangeMut, EntityStorage},
29};
30use crate::any::*;
31
32/// A trait implemented by an IR entity
33pub trait Entity: Any {}
34
35/// A trait implemented by an [Entity] that is a parent to one or more other [Entity] types.
36///
37/// Parents must implement this trait for each unique [EntityList] they contain.
38pub trait EntityParent<Child: ?Sized>: Entity {
39    /// Statically compute the offset of the [EntityList] within `Self` that is used to store
40    /// children of type `Child`.
41    fn offset() -> usize;
42}
43
44/// A trait implemented by an [Entity] that is a logical child of another entity type, and is stored
45/// in the parent using an [EntityList].
46///
47/// This trait defines callbacks that are executed any time the entity is modified in relation to its
48/// parent entity, i.e. inserted in a parent, removed from a parent, or moved from one to another.
49///
50/// By default, these callbacks are no-ops.
51pub trait EntityWithParent: Entity {
52    /// The parent entity that this entity logically belongs to.
53    type Parent: EntityParent<Self>;
54}
55
56/// A trait implemented by an [Entity] that has a unique identifier
57///
58/// Currently, this is used only for [crate::Value]s and [crate::Block]s.
59pub trait EntityWithId: Entity {
60    type Id: EntityId;
61
62    fn id(&self) -> Self::Id;
63}
64
65/// A trait implemented by an IR entity that can be stored in [EntityStorage].
66pub trait StorableEntity {
67    /// Get the absolute index of this entity in its container.
68    fn index(&self) -> usize;
69    /// Set the absolute index of this entity in its container.
70    ///
71    /// # Safety
72    ///
73    /// This is intended to be called only by the [EntityStorage] implementation, as it is
74    /// responsible for maintaining indices of all items it is storing. However, entities commonly
75    /// want to know their own index in storage, so this trait allows them to conceptually own the
76    /// index, but delegate maintenance to [EntityStorage].
77    unsafe fn set_index(&mut self, index: usize);
78    /// Called when this entity is removed from [EntityStorage]
79    #[inline(always)]
80    fn unlink(&mut self) {}
81}
82
83/// A trait that must be implemented by the unique identifier for an [Entity]
84pub trait EntityId: Copy + Clone + PartialEq + Eq + PartialOrd + Ord + Hash + fmt::Display {
85    fn as_usize(&self) -> usize;
86}
87
88/// An error raised when an aliasing violation is detected in the use of [UnsafeEntityRef]
89#[non_exhaustive]
90pub struct AliasingViolationError {
91    #[cfg(debug_assertions)]
92    location: &'static core::panic::Location<'static>,
93    kind: AliasingViolationKind,
94}
95
96#[derive(Debug)]
97enum AliasingViolationKind {
98    /// Attempted to create an immutable alias for an entity that was mutably borrowed
99    Immutable,
100    /// Attempted to create a mutable alias for an entity that was immutably borrowed
101    Mutable,
102}
103
104impl fmt::Display for AliasingViolationKind {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        match self {
107            Self::Immutable => f.write_str("already mutably borrowed"),
108            Self::Mutable => f.write_str("already borrowed"),
109        }
110    }
111}
112
113impl fmt::Debug for AliasingViolationError {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        let mut builder = f.debug_struct("AliasingViolationError");
116        builder.field("kind", &self.kind);
117        #[cfg(debug_assertions)]
118        builder.field("location", &self.location);
119        builder.finish()
120    }
121}
122impl fmt::Display for AliasingViolationError {
123    #[cfg(debug_assertions)]
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        write!(
126            f,
127            "{} in file '{}' at line {} and column {}",
128            &self.kind,
129            self.location.file(),
130            self.location.line(),
131            self.location.column()
132        )
133    }
134
135    #[cfg(not(debug_assertions))]
136    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137        write!(f, "{}", &self.kind)
138    }
139}
140
141/// A raw pointer to an IR entity that has no associated metadata
142pub type UnsafeEntityRef<T> = RawEntityRef<T, ()>;
143
144/// A raw pointer to an IR entity that has an intrusive linked-list link as its metadata
145pub type UnsafeIntrusiveEntityRef<T> = RawEntityRef<T, list::IntrusiveLink>;
146
147/// A raw pointer to an IR entity that has an intrusive red-black tree link as its metadata
148pub type UnsafeIntrusiveMapEntityRef<T> = RawEntityRef<T, map::IntrusiveLink>;
149
150/// A [RawEntityRef] is an unsafe smart pointer type for IR entities allocated in a [crate::Context].
151///
152/// Along with the type of entity referenced, it can be instantiated with extra metadata of any
153/// type. For example, [UnsafeIntrusiveEntityRef] stores an intrusive link in the entity metadata,
154/// so that the entity can be added to an intrusive linked list without the entity needing to
155/// know about the link - and without violating aliasing rules when navigating the list.
156///
157/// Unlike regular references, no reference to the underlying `T` is constructed until one is
158/// needed, at which point the borrow (whether mutable or immutable) is dynamically checked to
159/// ensure that it is valid according to Rust's aliasing rules.
160///
161/// As a result, a [RawEntityRef] is not considered an alias, and it is possible to acquire a
162/// mutable reference to the underlying data even while other copies of the handle exist. Any
163/// attempt to construct invalid aliases (immutable reference while a mutable reference exists, or
164/// vice versa), will result in a runtime panic.
165///
166/// This is a tradeoff, as we do not get compile-time guarantees that such panics will not occur,
167/// but in exchange we get a much more flexible and powerful IR structure.
168///
169/// # SAFETY
170///
171/// Unlike most smart-pointer types, e.g. `Rc`, [RawEntityRef] does not provide any protection
172/// against the underlying allocation being deallocated (i.e. the arena it points into is dropped).
173/// This is by design, as the type is meant to be stored in objects inside the arena, and
174/// _not_ dropped when the arena is dropped. This requires care when using it however, to ensure
175/// that no [RawEntityRef] lives longer than the arena that allocated it.
176///
177/// For a safe entity reference, see [EntityRef], which binds a [RawEntityRef] to the lifetime
178/// of the arena.
179pub struct RawEntityRef<T: ?Sized, Metadata = ()> {
180    inner: NonNull<RawEntityMetadata<T, Metadata>>,
181}
182impl<T: ?Sized, Metadata> Copy for RawEntityRef<T, Metadata> {}
183impl<T: ?Sized, Metadata> Clone for RawEntityRef<T, Metadata> {
184    fn clone(&self) -> Self {
185        *self
186    }
187}
188impl<T, Metadata> RawEntityRef<T, Metadata> {
189    /// Creates a new [RawEntityRef] that is dangling, but non-null and well-aligned.
190    ///
191    /// This is useful for initializing types which lazily allocate, similar to `Vec::new`.
192    ///
193    /// Note that the returned value contains a pointer which may potentially be valid, so it is
194    /// not safe to use this as a sentinel value for initialization - it is up to the caller to
195    /// track initialization by some other means.
196    pub const fn dangling() -> Self {
197        Self {
198            inner: NonNull::dangling(),
199        }
200    }
201}
202impl<T: ?Sized, Metadata> RawEntityRef<T, Metadata> {
203    /// Create a new [RawEntityRef] from a raw pointer to the underlying [EntityObj].
204    ///
205    /// # SAFETY
206    ///
207    /// [RawEntityRef] is designed to operate like an owned smart-pointer type, ala `Rc`. As a
208    /// result, it expects that the underlying data _never moves_ after it is allocated, for as
209    /// long as any outstanding [UnsafeEntityRef]s exist that might be used to access that data.
210    ///
211    /// Additionally, it is expected that all accesses to the underlying data flow through an
212    /// [RawEntityRef], as it is the foundation on which the soundness of [RawEntityRef] is
213    /// built. You must ensure that there no other references to the underlying data exist, or can
214    /// be created, _except_ via [RawEntityRef].
215    ///
216    /// You should generally not be using this API, as it is meant solely for constructing an
217    /// [RawEntityRef] immediately after allocating the underlying [Entity].
218    #[inline]
219    unsafe fn from_inner(inner: NonNull<RawEntityMetadata<T, Metadata>>) -> Self {
220        Self { inner }
221    }
222
223    #[inline]
224    unsafe fn from_ptr(ptr: *mut RawEntityMetadata<T, Metadata>) -> Self {
225        debug_assert!(!ptr.is_null());
226        unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) }
227    }
228
229    #[inline]
230    fn into_inner(this: Self) -> NonNull<RawEntityMetadata<T, Metadata>> {
231        this.inner
232    }
233}
234
235impl<T: 'static, Metadata: 'static> RawEntityRef<T, Metadata> {
236    /// Create a new [RawEntityRef] by allocating `value` with `metadata` in the given arena
237    /// allocator.
238    ///
239    /// # SAFETY
240    ///
241    /// The resulting [RawEntityRef] must not outlive the arena. This is not enforced statically,
242    /// it is up to the caller to uphold the invariants of this type.
243    pub fn new_with_metadata(value: T, metadata: Metadata, arena: &blink_alloc::Blink) -> Self {
244        unsafe {
245            Self::from_inner(NonNull::new_unchecked(
246                arena.put(RawEntityMetadata::new(value, metadata)),
247            ))
248        }
249    }
250
251    /// Create a [RawEntityRef] for an entity which may not be fully initialized, using the provided
252    /// arena.
253    ///
254    /// # SAFETY
255    ///
256    /// The safety rules are much the same as [RawEntityRef::new], with the main difference
257    /// being that the `T` does not have to be initialized yet. No references to the `T` will
258    /// be created directly until [RawEntityRef::assume_init] is called.
259    pub fn new_uninit_with_metadata(
260        metadata: Metadata,
261        arena: &blink_alloc::Blink,
262    ) -> RawEntityRef<MaybeUninit<T>, Metadata> {
263        unsafe {
264            RawEntityRef::from_ptr(RawEntityRef::allocate_for_layout(
265                metadata,
266                Layout::new::<T>(),
267                |layout| arena.allocator().allocate(layout).map_err(|_| AllocError),
268                <*mut u8>::cast,
269            ))
270        }
271    }
272}
273
274impl<T: 'static> RawEntityRef<T, ()> {
275    pub fn new(value: T, arena: &blink_alloc::Blink) -> Self {
276        RawEntityRef::new_with_metadata(value, (), arena)
277    }
278
279    pub fn new_uninit(arena: &blink_alloc::Blink) -> RawEntityRef<MaybeUninit<T>, ()> {
280        RawEntityRef::new_uninit_with_metadata((), arena)
281    }
282}
283
284impl<T, Metadata> RawEntityRef<MaybeUninit<T>, Metadata> {
285    /// Converts to `RawEntityRef<T>`.
286    ///
287    /// # Safety
288    ///
289    /// Just like with [MaybeUninit::assume_init], it is up to the caller to guarantee that the
290    /// value really is in an initialized state. Calling this when the content is not yet fully
291    /// initialized causes immediate undefined behavior.
292    #[inline]
293    pub unsafe fn assume_init(self) -> RawEntityRef<T, Metadata> {
294        let ptr = Self::into_inner(self);
295        unsafe { RawEntityRef::from_inner(ptr.cast()) }
296    }
297}
298
299impl<T: ?Sized, Metadata> RawEntityRef<T, Metadata> {
300    /// Convert this handle into a raw pointer to the underlying entity.
301    ///
302    /// This should only be used in situations where the returned pointer will not be used to
303    /// actually access the underlying entity. Use [Self::borrow] or [Self::borrow_mut] for that.
304    /// [RawEntityRef] ensures that Rust's aliasing rules are not violated when using it, but if you
305    /// use the returned pointer to do so, no such guarantee is provided, and undefined behavior can
306    /// result.
307    ///
308    /// # Safety
309    ///
310    /// The returned pointer _must_ not be used to create a reference to the underlying entity
311    /// unless you can guarantee that such a reference does not violate Rust's aliasing rules.
312    ///
313    /// Do not use the pointer to create a mutable reference if other references exist, and do
314    /// not use the pointer to create an immutable reference if a mutable reference exists or
315    /// might be created while the immutable reference lives.
316    pub fn into_raw(this: Self) -> *const T {
317        Self::as_ptr(&this)
318    }
319
320    pub fn as_ptr(this: &Self) -> *const T {
321        let ptr: *mut RawEntityMetadata<T, Metadata> = NonNull::as_ptr(this.inner);
322
323        // SAFETY: This cannot go through Deref::deref or RawEntityRef::inner because this
324        // is required to retain raw/mut provenance such that e.g. `get_mut` can write through
325        // the pointer after the RawEntityRef is recovered through `from_raw`
326        let ptr = unsafe { core::ptr::addr_of_mut!((*ptr).entity.cell) };
327        UnsafeCell::raw_get(ptr).cast_const()
328    }
329
330    /// Convert a pointer returned by [RawEntityRef::into_raw] back into a [RawEntityRef].
331    ///
332    /// # Safety
333    ///
334    /// * It is _only_ valid to call this method on a pointer returned by [RawEntityRef::into_raw].
335    /// * The pointer must be a valid pointer for `T`
336    pub unsafe fn from_raw(ptr: *const T) -> Self {
337        let offset = unsafe { RawEntityMetadata::<T, Metadata>::data_offset(ptr) };
338
339        // Reverse the offset to find the original EntityObj
340        let entity_ptr = unsafe { ptr.byte_sub(offset) as *mut RawEntityMetadata<T, Metadata> };
341
342        unsafe { Self::from_ptr(entity_ptr) }
343    }
344
345    /// Get a dynamically-checked immutable reference to the underlying `T`
346    #[track_caller]
347    pub fn borrow<'a, 'b: 'a>(&'a self) -> EntityRef<'b, T> {
348        let ptr: *mut RawEntityMetadata<T, Metadata> = NonNull::as_ptr(self.inner);
349        let borrow = unsafe { (*core::ptr::addr_of!((*ptr).entity)).borrow() };
350        let value = unsafe { NonNull::new_unchecked(Self::as_ptr(self).cast_mut()) };
351        EntityRef::from_raw_parts(value, borrow.into_borrow_ref())
352    }
353
354    /// Get a dynamically-checked mutable reference to the underlying `T`
355    #[track_caller]
356    pub fn borrow_mut<'a, 'b: 'a>(&'a mut self) -> EntityMut<'b, T> {
357        let ptr: *mut RawEntityMetadata<T, Metadata> = NonNull::as_ptr(self.inner);
358        let borrow = unsafe { (*core::ptr::addr_of!((*ptr).entity)).borrow_mut() };
359        let value = unsafe { NonNull::new_unchecked(Self::as_ptr(self).cast_mut()) };
360        EntityMut::from_raw_parts(value, borrow.into_borrow_ref_mut())
361    }
362
363    /// Try to get a dynamically-checked mutable reference to the underlying `T`
364    ///
365    /// Returns `None` if the entity is already borrowed
366    pub fn try_borrow_mut<'a, 'b: 'a>(&'a mut self) -> Option<EntityMut<'b, T>> {
367        let ptr: *mut RawEntityMetadata<T, Metadata> = NonNull::as_ptr(self.inner);
368        unsafe { (*core::ptr::addr_of!((*ptr).entity)).try_borrow_mut().ok() }.map(|borrow| {
369            let value = unsafe { NonNull::new_unchecked(Self::as_ptr(self).cast_mut()) };
370            EntityMut::from_raw_parts(value, borrow.into_borrow_ref_mut())
371        })
372    }
373
374    pub fn ptr_eq(this: &Self, other: &Self) -> bool {
375        core::ptr::addr_eq(this.inner.as_ptr(), other.inner.as_ptr())
376    }
377
378    unsafe fn allocate_for_layout<F, F2>(
379        metadata: Metadata,
380        value_layout: Layout,
381        allocate: F,
382        mem_to_metadata: F2,
383    ) -> *mut RawEntityMetadata<T, Metadata>
384    where
385        F: FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
386        F2: FnOnce(*mut u8) -> *mut RawEntityMetadata<T, Metadata>,
387    {
388        use alloc::alloc::handle_alloc_error;
389
390        let layout = raw_entity_metadata_layout_for_value_layout::<Metadata>(value_layout);
391        unsafe {
392            RawEntityRef::try_allocate_for_layout(metadata, value_layout, allocate, mem_to_metadata)
393                .unwrap_or_else(|_| handle_alloc_error(layout))
394        }
395    }
396
397    #[inline]
398    unsafe fn try_allocate_for_layout<F, F2>(
399        metadata: Metadata,
400        value_layout: Layout,
401        allocate: F,
402        mem_to_metadata: F2,
403    ) -> Result<*mut RawEntityMetadata<T, Metadata>, AllocError>
404    where
405        F: FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
406        F2: FnOnce(*mut u8) -> *mut RawEntityMetadata<T, Metadata>,
407    {
408        let layout = raw_entity_metadata_layout_for_value_layout::<Metadata>(value_layout);
409        let ptr = allocate(layout)?;
410        let inner = mem_to_metadata(ptr.as_non_null_ptr().as_ptr());
411        unsafe {
412            debug_assert_eq!(Layout::for_value_raw(inner), layout);
413
414            core::ptr::addr_of_mut!((*inner).metadata).write(metadata);
415            core::ptr::addr_of_mut!((*inner).entity.borrow).write(Cell::new(BorrowFlag::UNUSED));
416            #[cfg(debug_assertions)]
417            core::ptr::addr_of_mut!((*inner).entity.borrowed_at).write(Cell::new(None));
418        }
419
420        Ok(inner)
421    }
422}
423
424impl<From: ?Sized, Metadata: 'static> RawEntityRef<From, Metadata> {
425    /// Cast this handle to a different pointee type without validating the cast.
426    ///
427    /// # Safety
428    ///
429    /// Callers must ensure that `To` refers to the same allocation as `self`.
430    #[inline(always)]
431    pub(crate) unsafe fn cast_unchecked<To>(self) -> RawEntityRef<To, Metadata>
432    where
433        To: Sized,
434    {
435        unsafe { RawEntityRef::from_inner(self.inner.cast()) }
436    }
437
438    /// Cast this handle to an unsized pointee type without validating the cast.
439    ///
440    /// # Safety
441    ///
442    /// Callers must ensure that `To` refers to the same allocation as `self`, and that `metadata`
443    /// matches the target pointee type for that allocation.
444    #[inline(always)]
445    pub(crate) unsafe fn cast_unsized_unchecked<To>(
446        self,
447        metadata: <To as core::ptr::Pointee>::Metadata,
448    ) -> RawEntityRef<To, Metadata>
449    where
450        To: ?Sized + core::ptr::Pointee,
451    {
452        let inner = core::ptr::from_raw_parts_mut(self.inner.as_ptr().cast::<()>(), metadata);
453        unsafe { RawEntityRef::from_ptr(inner) }
454    }
455
456    /// Casts this reference to the an unsized type `Trait`, if `From` implements `Trait`
457    ///
458    /// If the cast is not valid for this reference, `Err` is returned containing the original value.
459    #[inline]
460    pub fn upcast<To>(self) -> RawEntityRef<To, Metadata>
461    where
462        To: ?Sized,
463        From: core::marker::Unsize<To> + AsAny + 'static,
464    {
465        unsafe { RawEntityRef::<To, Metadata>::from_inner(self.inner) }
466    }
467}
468
469impl<T: crate::Op> RawEntityRef<T, list::IntrusiveLink> {
470    /// Get a entity ref for the underlying [crate::Operation] data of an [crate::Op].
471    pub fn as_operation_ref(self) -> crate::OperationRef {
472        // SAFETY: This relies on the fact that we generate Op implementations such that the first
473        // field is always the [crate::Operation], and that the containing struct is #[repr(C)].
474        unsafe {
475            let ptr = Self::into_raw(self);
476            crate::OperationRef::from_raw(ptr.cast())
477        }
478    }
479}
480
481impl<T: crate::Attribute> RawEntityRef<T, list::IntrusiveLink> {
482    /// Convert this reference to an [crate::AttributeRef]
483    #[inline(always)]
484    pub fn as_attribute_ref(self) -> crate::AttributeRef {
485        self.upcast()
486    }
487}
488
489impl<T, U, Metadata> core::ops::CoerceUnsized<RawEntityRef<U, Metadata>>
490    for RawEntityRef<T, Metadata>
491where
492    T: ?Sized + core::marker::Unsize<U>,
493    U: ?Sized,
494{
495}
496impl<T: ?Sized, Metadata> Eq for RawEntityRef<T, Metadata> {}
497impl<T: ?Sized, Metadata> PartialEq for RawEntityRef<T, Metadata> {
498    #[inline]
499    default fn eq(&self, other: &Self) -> bool {
500        Self::ptr_eq(self, other)
501    }
502}
503impl<T: ?Sized + EntityWithId, Metadata> PartialOrd for RawEntityRef<T, Metadata> {
504    #[inline]
505    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
506        Some(self.cmp(other))
507    }
508}
509impl<T: ?Sized + EntityWithId, Metadata> Ord for RawEntityRef<T, Metadata> {
510    #[inline]
511    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
512        self.borrow().id().cmp(&other.borrow().id())
513    }
514}
515impl<T: ?Sized, Metadata> core::hash::Hash for RawEntityRef<T, Metadata> {
516    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
517        self.inner.as_ptr().addr().hash(state);
518    }
519}
520impl<T: ?Sized, Metadata> fmt::Pointer for RawEntityRef<T, Metadata> {
521    #[inline]
522    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
523        fmt::Pointer::fmt(&Self::as_ptr(self), f)
524    }
525}
526impl<T: ?Sized + fmt::Display, Metadata> fmt::Display for RawEntityRef<T, Metadata> {
527    #[inline]
528    default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
529        write!(f, "{}", self.borrow())
530    }
531}
532impl<T: ?Sized + fmt::Display + EntityWithId, Metadata> fmt::Display for RawEntityRef<T, Metadata> {
533    #[inline]
534    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
535        write!(f, "{}", self.borrow().id())
536    }
537}
538
539impl<T: ?Sized + fmt::Debug, Metadata> fmt::Debug for RawEntityRef<T, Metadata> {
540    #[inline]
541    default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
542        fmt::Debug::fmt(&self.borrow(), f)
543    }
544}
545impl<T: ?Sized + fmt::Debug + EntityWithId, Metadata> fmt::Debug for RawEntityRef<T, Metadata> {
546    #[inline]
547    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
548        write!(f, "{}", self.borrow().id())
549    }
550}
551impl<T: ?Sized + crate::formatter::PrettyPrint, Metadata> crate::formatter::PrettyPrint
552    for RawEntityRef<T, Metadata>
553{
554    #[inline]
555    fn render(&self) -> crate::formatter::Document {
556        self.borrow().render()
557    }
558}
559impl<T: ?Sized + StorableEntity, Metadata> StorableEntity for RawEntityRef<T, Metadata> {
560    #[inline]
561    fn index(&self) -> usize {
562        self.borrow().index()
563    }
564
565    #[inline]
566    unsafe fn set_index(&mut self, index: usize) {
567        unsafe {
568            self.borrow_mut().set_index(index);
569        }
570    }
571
572    #[inline]
573    fn unlink(&mut self) {
574        self.borrow_mut().unlink()
575    }
576}
577impl<T: ?Sized + crate::Spanned, Metadata> crate::Spanned for RawEntityRef<T, Metadata> {
578    #[inline]
579    fn span(&self) -> crate::SourceSpan {
580        self.borrow().span()
581    }
582}
583
584/// A guard that ensures a reference to an IR entity cannot be mutably aliased
585pub struct EntityRef<'b, T: ?Sized + 'b> {
586    value: NonNull<T>,
587    borrow: BorrowRef<'b>,
588}
589impl<T: ?Sized> AsRef<T> for EntityRef<'_, T> {
590    default fn as_ref(&self) -> &T {
591        // SAFETY: the value is accessible as long as we hold our borrow.
592        unsafe { self.value.as_ref() }
593    }
594}
595impl<T: super::Op> AsRef<super::Operation> for EntityRef<'_, T> {
596    fn as_ref(&self) -> &super::Operation {
597        // SAFETY: the value is accessible as long as we hold our borrow.
598        unsafe { self.value.as_ref().as_operation() }
599    }
600}
601impl<T: ?Sized> core::ops::Deref for EntityRef<'_, T> {
602    type Target = T;
603
604    fn deref(&self) -> &Self::Target {
605        // SAFETY: the value is accessible as long as we hold our borrow.
606        unsafe { self.value.as_ref() }
607    }
608}
609impl<'b, T: ?Sized> EntityRef<'b, T> {
610    /// Map this reference to a derived reference.
611    #[inline]
612    pub fn map<U: ?Sized, F>(orig: Self, f: F) -> EntityRef<'b, U>
613    where
614        F: FnOnce(&T) -> &U,
615    {
616        EntityRef {
617            value: NonNull::from(f(&*orig)),
618            borrow: orig.borrow,
619        }
620    }
621
622    /// Project this borrow into a owned (but semantically borrowed) value that inherits ownership
623    /// of the underlying borrow.
624    pub fn project<'to, 'from: 'to, To, F>(
625        orig: EntityRef<'from, T>,
626        f: F,
627    ) -> EntityProjection<'from, To>
628    where
629        F: FnOnce(&'to T) -> To,
630        To: 'to,
631    {
632        EntityProjection {
633            value: f(unsafe { orig.value.as_ref() }),
634            borrow: orig.borrow,
635        }
636    }
637
638    /// Try to convert this immutable borrow into a mutable borrow, if it is the only immutable borrow
639    pub fn into_entity_mut(self) -> Result<EntityMut<'b, T>, Self> {
640        let value = self.value;
641        match self.borrow.try_into_mut() {
642            Ok(borrow) => Ok(EntityMut {
643                value,
644                borrow,
645                _marker: core::marker::PhantomData,
646            }),
647            Err(borrow) => Err(Self { value, borrow }),
648        }
649    }
650
651    pub fn into_borrow_ref(self) -> BorrowRef<'b> {
652        self.borrow
653    }
654
655    pub fn from_raw_parts(value: NonNull<T>, borrow: BorrowRef<'b>) -> Self {
656        Self { value, borrow }
657    }
658}
659impl<T: crate::Attribute> EntityRef<'_, T> {
660    /// Reconstitutes the type-erased intrusive handle for this borrowed attribute.
661    pub fn as_attribute_ref(&self) -> crate::AttributeRef {
662        unsafe { RawEntityRef::<T, list::IntrusiveLink>::from_raw(self.value.as_ptr()) }
663            .as_attribute_ref()
664    }
665}
666impl EntityRef<'_, dyn crate::Attribute> {
667    /// Reconstitutes the type-erased intrusive handle for this borrowed attribute.
668    pub fn as_attribute_ref(&self) -> crate::AttributeRef {
669        unsafe { crate::AttributeRef::from_raw(self.value.as_ptr()) }
670    }
671}
672impl<'b, T, U> core::ops::CoerceUnsized<EntityRef<'b, U>> for EntityRef<'b, T>
673where
674    T: ?Sized + core::marker::Unsize<U>,
675    U: ?Sized,
676{
677}
678
679impl<T: ?Sized + fmt::Debug> fmt::Debug for EntityRef<'_, T> {
680    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
681        (**self).fmt(f)
682    }
683}
684impl<T: ?Sized + fmt::Display> fmt::Display for EntityRef<'_, T> {
685    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
686        (**self).fmt(f)
687    }
688}
689impl<T: ?Sized + crate::formatter::PrettyPrint> crate::formatter::PrettyPrint for EntityRef<'_, T> {
690    #[inline]
691    fn render(&self) -> crate::formatter::Document {
692        (**self).render()
693    }
694}
695impl<T: ?Sized + Eq> Eq for EntityRef<'_, T> {}
696impl<T: ?Sized + PartialEq> PartialEq for EntityRef<'_, T> {
697    fn eq(&self, other: &Self) -> bool {
698        **self == **other
699    }
700}
701impl<T: ?Sized + PartialOrd> PartialOrd for EntityRef<'_, T> {
702    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
703        (**self).partial_cmp(&**other)
704    }
705
706    fn ge(&self, other: &Self) -> bool {
707        **self >= **other
708    }
709
710    fn gt(&self, other: &Self) -> bool {
711        **self > **other
712    }
713
714    fn le(&self, other: &Self) -> bool {
715        **self <= **other
716    }
717
718    fn lt(&self, other: &Self) -> bool {
719        **self < **other
720    }
721}
722impl<T: ?Sized + Ord> Ord for EntityRef<'_, T> {
723    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
724        (**self).cmp(&**other)
725    }
726}
727impl<T: ?Sized + Hash> Hash for EntityRef<'_, T> {
728    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
729        (**self).hash(state);
730    }
731}
732
733/// A guard that provides exclusive access to an IR entity
734pub struct EntityMut<'b, T: ?Sized> {
735    /// The raw pointer to the underlying data
736    ///
737    /// This is a pointer rather than a `&'b mut T` to avoid `noalias` violations, because a
738    /// `EntityMut` argument doesn't hold exclusivity for its whole scope, only until it drops.
739    value: NonNull<T>,
740    /// This value provides the drop glue for tracking that the underlying allocation is
741    /// mutably borrowed, but it is otherwise not read.
742    #[allow(unused)]
743    borrow: BorrowRefMut<'b>,
744    /// `NonNull` is covariant over `T`, so we need to reintroduce invariance via phantom data
745    _marker: core::marker::PhantomData<&'b mut T>,
746}
747impl<'b, T: ?Sized> EntityMut<'b, T> {
748    /// Map this mutable reference to a derived mutable reference.
749    #[inline]
750    pub fn map<U: ?Sized, F>(mut orig: Self, f: F) -> EntityMut<'b, U>
751    where
752        F: FnOnce(&mut T) -> &mut U,
753    {
754        let value = NonNull::from(f(&mut *orig));
755        EntityMut {
756            value,
757            borrow: orig.borrow,
758            _marker: core::marker::PhantomData,
759        }
760    }
761
762    /// Project this mutable borrow into a owned (but semantically borrowed) value that inherits
763    /// ownership of the underlying mutable borrow.
764    pub fn project<'to, 'from: 'to, To, F>(
765        mut orig: EntityMut<'from, T>,
766        f: F,
767    ) -> EntityProjectionMut<'from, To>
768    where
769        F: FnOnce(&'to mut T) -> To,
770        To: 'to,
771    {
772        EntityProjectionMut {
773            value: f(unsafe { orig.value.as_mut() }),
774            borrow: orig.borrow,
775        }
776    }
777
778    /// Splits an `EntityMut` into multiple `EntityMut`s for different components of the borrowed
779    /// data.
780    ///
781    /// The underlying entity will remain mutably borrowed until both returned `EntityMut`s go out
782    /// of scope.
783    ///
784    /// The entity is already mutably borrowed, so this cannot fail.
785    ///
786    /// This is an associated function that needs to be used as `EntityMut::map_split(...)`, so as
787    /// to avoid conflicting with any method of the same name accessible via the `Deref` impl.
788    ///
789    /// # Examples
790    ///
791    /// ```rust
792    /// use midenc_hir::*;
793    /// use blink_alloc::Blink;
794    ///
795    /// let alloc = Blink::default();
796    /// let mut entity = UnsafeEntityRef::new([1, 2, 3, 4], &alloc);
797    /// let borrow = entity.borrow_mut();
798    /// let (mut begin, mut end) = EntityMut::map_split(borrow, |slice| slice.split_at_mut(2));
799    /// assert_eq!(*begin, [1, 2]);
800    /// assert_eq!(*end, [3, 4]);
801    /// begin.copy_from_slice(&[4, 3]);
802    /// end.copy_from_slice(&[2, 1]);
803    /// ```
804    #[inline]
805    pub fn map_split<U: ?Sized, V: ?Sized, F>(
806        mut orig: Self,
807        f: F,
808    ) -> (EntityMut<'b, U>, EntityMut<'b, V>)
809    where
810        F: FnOnce(&mut T) -> (&mut U, &mut V),
811    {
812        let borrow = orig.borrow.clone();
813        let (a, b) = f(&mut *orig);
814        (
815            EntityMut {
816                value: NonNull::from(a),
817                borrow,
818                _marker: core::marker::PhantomData,
819            },
820            EntityMut {
821                value: NonNull::from(b),
822                borrow: orig.borrow,
823                _marker: core::marker::PhantomData,
824            },
825        )
826    }
827
828    /// Convert this mutable borrow into an immutable borrow
829    pub fn into_entity_ref(self) -> EntityRef<'b, T> {
830        let value = self.value;
831        let borrow = self.into_borrow_ref_mut();
832
833        EntityRef {
834            value,
835            borrow: borrow.into_borrow_ref(),
836        }
837    }
838
839    #[doc(hidden)]
840    pub(crate) fn into_borrow_ref_mut(self) -> BorrowRefMut<'b> {
841        self.borrow
842    }
843
844    #[allow(unused)]
845    pub(crate) fn from_raw_parts(value: NonNull<T>, borrow: BorrowRefMut<'b>) -> Self {
846        Self {
847            value,
848            borrow,
849            _marker: core::marker::PhantomData,
850        }
851    }
852}
853impl<T: ?Sized> Deref for EntityMut<'_, T> {
854    type Target = T;
855
856    #[inline]
857    fn deref(&self) -> &T {
858        // SAFETY: the value is accessible as long as we hold our borrow.
859        unsafe { self.value.as_ref() }
860    }
861}
862impl<T: ?Sized> DerefMut for EntityMut<'_, T> {
863    #[inline]
864    fn deref_mut(&mut self) -> &mut T {
865        // SAFETY: the value is accessible as long as we hold our borrow.
866        unsafe { self.value.as_mut() }
867    }
868}
869impl<'b, T, U> core::ops::CoerceUnsized<EntityMut<'b, U>> for EntityMut<'b, T>
870where
871    T: ?Sized + core::marker::Unsize<U>,
872    U: ?Sized,
873{
874}
875
876impl<T: ?Sized + fmt::Debug> fmt::Debug for EntityMut<'_, T> {
877    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
878        (**self).fmt(f)
879    }
880}
881impl<T: ?Sized + fmt::Display> fmt::Display for EntityMut<'_, T> {
882    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
883        (**self).fmt(f)
884    }
885}
886impl<T: ?Sized + crate::formatter::PrettyPrint> crate::formatter::PrettyPrint for EntityMut<'_, T> {
887    #[inline]
888    fn render(&self) -> crate::formatter::Document {
889        (**self).render()
890    }
891}
892impl<T: ?Sized + Eq> Eq for EntityMut<'_, T> {}
893impl<T: ?Sized + PartialEq> PartialEq for EntityMut<'_, T> {
894    fn eq(&self, other: &Self) -> bool {
895        **self == **other
896    }
897}
898impl<T: ?Sized + PartialOrd> PartialOrd for EntityMut<'_, T> {
899    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
900        (**self).partial_cmp(&**other)
901    }
902
903    fn ge(&self, other: &Self) -> bool {
904        **self >= **other
905    }
906
907    fn gt(&self, other: &Self) -> bool {
908        **self > **other
909    }
910
911    fn le(&self, other: &Self) -> bool {
912        **self <= **other
913    }
914
915    fn lt(&self, other: &Self) -> bool {
916        **self < **other
917    }
918}
919impl<T: ?Sized + Ord> Ord for EntityMut<'_, T> {
920    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
921        (**self).cmp(&**other)
922    }
923}
924impl<T: ?Sized + Hash> Hash for EntityMut<'_, T> {
925    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
926        (**self).hash(state);
927    }
928}
929
930/// Represents a projection of an [EntityRef] into an owned value.
931///
932/// This retains the lifetime of the borrow, while allowing the projection itself to be owned. This
933/// is useful in cases where you would like to return a value derived from an [EntityRef] from a
934/// function, when the borrowed entity outlives the function itself. Since [EntityRef] can only
935/// represent references, deriving owned (but semantically borrowed) values from an [EntityRef]
936/// cannot be returned from an enclosing function, unlike if the value was a reference.
937///
938/// NOTE: An [EntityProjection] takes ownership of the [EntityRef] from which it was derived, and
939/// propagates the lifetime of the borrowed entity. When this type is dropped, so is the original
940/// borrow.
941pub struct EntityProjection<'b, T: 'b> {
942    borrow: BorrowRef<'b>,
943    value: T,
944}
945impl<T> core::ops::Deref for EntityProjection<'_, T> {
946    type Target = T;
947
948    #[inline(always)]
949    fn deref(&self) -> &Self::Target {
950        &self.value
951    }
952}
953impl<T> core::ops::DerefMut for EntityProjection<'_, T> {
954    #[inline(always)]
955    fn deref_mut(&mut self) -> &mut Self::Target {
956        &mut self.value
957    }
958}
959impl<'b, T> EntityProjection<'b, T> {
960    pub fn map<U, F>(orig: Self, f: F) -> EntityProjection<'b, U>
961    where
962        F: FnOnce(T) -> U,
963    {
964        EntityProjection {
965            value: f(orig.value),
966            borrow: orig.borrow,
967        }
968    }
969}
970impl<T: fmt::Debug> fmt::Debug for EntityProjection<'_, T> {
971    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
972        fmt::Debug::fmt(&self.value, f)
973    }
974}
975impl<T: fmt::Display> fmt::Display for EntityProjection<'_, T> {
976    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
977        fmt::Display::fmt(&self.value, f)
978    }
979}
980impl<T: crate::formatter::PrettyPrint> crate::formatter::PrettyPrint for EntityProjection<'_, T> {
981    #[inline]
982    fn render(&self) -> crate::formatter::Document {
983        crate::formatter::PrettyPrint::render(&self.value)
984    }
985}
986impl<T: Eq> Eq for EntityProjection<'_, T> {}
987impl<T: PartialEq> PartialEq for EntityProjection<'_, T> {
988    fn eq(&self, other: &Self) -> bool {
989        self.value == other.value
990    }
991}
992impl<T: PartialOrd> PartialOrd for EntityProjection<'_, T> {
993    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
994        self.value.partial_cmp(&other.value)
995    }
996
997    fn ge(&self, other: &Self) -> bool {
998        self.value.ge(&other.value)
999    }
1000
1001    fn gt(&self, other: &Self) -> bool {
1002        self.value.gt(&other.value)
1003    }
1004
1005    fn le(&self, other: &Self) -> bool {
1006        self.value.le(&other.value)
1007    }
1008
1009    fn lt(&self, other: &Self) -> bool {
1010        self.value.lt(&other.value)
1011    }
1012}
1013impl<T: Ord> Ord for EntityProjection<'_, T> {
1014    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
1015        self.value.cmp(&other.value)
1016    }
1017}
1018impl<T: Hash> Hash for EntityProjection<'_, T> {
1019    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1020        self.value.hash(state)
1021    }
1022}
1023
1024/// Represents a projection of an [EntityMut] into an owned value.
1025///
1026/// This retains the lifetime of the borrow, while allowing the projection itself to be owned. This
1027/// is useful in cases where you would like to return a value derived from an [EntityMut] from a
1028/// function, when the borrowed entity outlives the function itself. Since [EntityMut] can only
1029/// represent references, deriving owned (but semantically borrowed) values from an [EntityMut]
1030/// cannot be returned from an enclosing function, unlike if the value was a reference.
1031///
1032/// NOTE: An [EntityProjectionMut] takes ownership of the [EntityMut] from which it was derived, and
1033/// propagates the lifetime of the borrowed entity. When this type is dropped, so is the original
1034/// borrow.
1035pub struct EntityProjectionMut<'b, T: 'b> {
1036    borrow: BorrowRefMut<'b>,
1037    value: T,
1038}
1039impl<T> core::ops::Deref for EntityProjectionMut<'_, T> {
1040    type Target = T;
1041
1042    #[inline(always)]
1043    fn deref(&self) -> &Self::Target {
1044        &self.value
1045    }
1046}
1047impl<T> core::ops::DerefMut for EntityProjectionMut<'_, T> {
1048    #[inline(always)]
1049    fn deref_mut(&mut self) -> &mut Self::Target {
1050        &mut self.value
1051    }
1052}
1053impl<'b, T> EntityProjectionMut<'b, T> {
1054    pub fn map<U, F>(orig: Self, f: F) -> EntityProjectionMut<'b, U>
1055    where
1056        F: FnOnce(T) -> U,
1057    {
1058        EntityProjectionMut {
1059            value: f(orig.value),
1060            borrow: orig.borrow,
1061        }
1062    }
1063}
1064impl<T: fmt::Debug> fmt::Debug for EntityProjectionMut<'_, T> {
1065    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1066        fmt::Debug::fmt(&self.value, f)
1067    }
1068}
1069impl<T: fmt::Display> fmt::Display for EntityProjectionMut<'_, T> {
1070    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1071        fmt::Display::fmt(&self.value, f)
1072    }
1073}
1074impl<T: crate::formatter::PrettyPrint> crate::formatter::PrettyPrint
1075    for EntityProjectionMut<'_, T>
1076{
1077    #[inline]
1078    fn render(&self) -> crate::formatter::Document {
1079        crate::formatter::PrettyPrint::render(&self.value)
1080    }
1081}
1082impl<T: Eq> Eq for EntityProjectionMut<'_, T> {}
1083impl<T: PartialEq> PartialEq for EntityProjectionMut<'_, T> {
1084    fn eq(&self, other: &Self) -> bool {
1085        self.value == other.value
1086    }
1087}
1088impl<T: PartialOrd> PartialOrd for EntityProjectionMut<'_, T> {
1089    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
1090        self.value.partial_cmp(&other.value)
1091    }
1092
1093    fn ge(&self, other: &Self) -> bool {
1094        self.value.ge(&other.value)
1095    }
1096
1097    fn gt(&self, other: &Self) -> bool {
1098        self.value.gt(&other.value)
1099    }
1100
1101    fn le(&self, other: &Self) -> bool {
1102        self.value.le(&other.value)
1103    }
1104
1105    fn lt(&self, other: &Self) -> bool {
1106        self.value.lt(&other.value)
1107    }
1108}
1109impl<T: Ord> Ord for EntityProjectionMut<'_, T> {
1110    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
1111        self.value.cmp(&other.value)
1112    }
1113}
1114impl<T: Hash> Hash for EntityProjectionMut<'_, T> {
1115    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
1116        self.value.hash(state)
1117    }
1118}
1119
1120// This type wraps the entity data with extra metadata we want to associate with the entity, but
1121// separately from it, so that pointers to the metadata do not cause aliasing violations if the
1122// entity itself is borrowed.
1123//
1124// The kind of metadata stored here is unconstrained, but in practice should be limited to things
1125// that you _need_ to be able to access from a `RawEntityRef`, without aliasing the entity. For now
1126// the main reason we use this is for the intrusive link used to store entities in an intrusive
1127// linked list. We don't want traversing the intrusive list to require borrowing the entity, only
1128// the link, unless we explicitly want to borrow the entity, thus we use the metadata field here
1129// to hold the link.
1130//
1131// This has to be `pub` for implementing the traits required for the intrusive collections
1132// integration, but its internals are hidden outside this module, and we hide it from the generated
1133// docs as well.
1134#[repr(C)]
1135#[doc(hidden)]
1136pub struct RawEntityMetadata<T: ?Sized, Metadata> {
1137    metadata: Metadata,
1138    entity: RawEntity<T>,
1139}
1140impl<T, Metadata> RawEntityMetadata<T, Metadata> {
1141    pub(crate) fn new(value: T, metadata: Metadata) -> Self {
1142        Self {
1143            metadata,
1144            entity: RawEntity::new(value),
1145        }
1146    }
1147}
1148impl<T: ?Sized, Metadata> RawEntityMetadata<T, Metadata> {
1149    #[track_caller]
1150    pub(crate) fn borrow(&self) -> EntityRef<'_, T> {
1151        self.entity.borrow()
1152    }
1153
1154    #[track_caller]
1155    pub(crate) fn borrow_mut(&self) -> EntityMut<'_, T> {
1156        self.entity.borrow_mut()
1157    }
1158
1159    #[inline]
1160    const fn metadata_offset() -> usize {
1161        core::mem::offset_of!(RawEntityMetadata<(), Metadata>, metadata)
1162    }
1163
1164    /// Get the offset within a `RawEntityMetadata` for the payload behind a pointer.
1165    ///
1166    /// # Safety
1167    ///
1168    /// The pointer must point to (and have valid metadata for) a previously valid instance of T, but
1169    /// the T is allowed to be dropped.
1170    unsafe fn data_offset(ptr: *const T) -> usize {
1171        // Align the unsized value to the end of the RawEntityMetadata.
1172        // Because RawEntityMetadata/RawEntity is repr(C), it will always be the last field in memory.
1173        //
1174        // SAFETY: since the only unsized types possible are slices, trait objects, and extern types,
1175        // the input safety requirement is currently enough to satisfy the requirements of
1176        // align_of_val_raw; but this is an implementation detail of the language that is unstable
1177        let align = unsafe { core::mem::Alignment::of_val_raw(ptr) };
1178        RawEntityMetadata::<(), Metadata>::data_offset_align(align)
1179    }
1180
1181    #[inline]
1182    fn data_offset_align(align: core::mem::Alignment) -> usize {
1183        raw_entity_value_offset_for_align::<Metadata>(align)
1184    }
1185}
1186
1187fn raw_entity_metadata_layout_for_value_layout<Metadata>(layout: Layout) -> Layout {
1188    let value_offset = raw_entity_value_offset_for_align::<Metadata>(layout.alignment());
1189    let header_layout = Layout::new::<RawEntity<()>>();
1190    let align = Layout::new::<Metadata>().align().max(header_layout.align()).max(layout.align());
1191    Layout::from_size_align(value_offset + layout.size(), align)
1192        .unwrap()
1193        .pad_to_align()
1194}
1195
1196fn raw_entity_value_offset_for_align<Metadata>(value_align: core::mem::Alignment) -> usize {
1197    let metadata_layout = Layout::new::<Metadata>();
1198    let header_layout = Layout::new::<RawEntity<()>>();
1199    let entity_align = header_layout.alignment().max(value_align);
1200    let entity_offset = metadata_layout.size() + metadata_layout.padding_needed_for(entity_align);
1201    let cell_offset = header_layout.size() + header_layout.padding_needed_for(value_align);
1202    entity_offset + cell_offset
1203}
1204
1205/// A [RawEntity] wraps an entity to be allocated in a [crate::Context], and provides dynamic borrow-
1206/// checking functionality for [UnsafeEntityRef], thereby protecting the entity by ensuring that
1207/// all accesses adhere to Rust's aliasing rules.
1208#[repr(C)]
1209pub struct RawEntity<T: ?Sized> {
1210    borrow: Cell<BorrowFlag>,
1211    #[cfg(debug_assertions)]
1212    borrowed_at: Cell<Option<&'static core::panic::Location<'static>>>,
1213    cell: UnsafeCell<T>,
1214}
1215
1216impl<T> RawEntity<T> {
1217    pub fn new(value: T) -> Self {
1218        Self {
1219            borrow: Cell::new(BorrowFlag::UNUSED),
1220            #[cfg(debug_assertions)]
1221            borrowed_at: Cell::new(None),
1222            cell: UnsafeCell::new(value),
1223        }
1224    }
1225
1226    #[allow(unused)]
1227    #[doc(hidden)]
1228    #[inline(always)]
1229    pub(crate) fn entity_addr(&self) -> *mut T {
1230        self.cell.get()
1231    }
1232
1233    #[allow(unused)]
1234    #[doc(hidden)]
1235    #[inline(always)]
1236    pub(crate) const fn entity_offset(&self) -> usize {
1237        core::mem::offset_of!(Self, cell)
1238    }
1239}
1240
1241impl<T, U> core::ops::CoerceUnsized<RawEntity<U>> for RawEntity<T> where
1242    T: core::ops::CoerceUnsized<U>
1243{
1244}
1245
1246impl<T: ?Sized> RawEntity<T> {
1247    /// Construct a borrow of this [RawEntity], returning the raw borrow components.
1248    ///
1249    /// # Safety
1250    ///
1251    /// Callers may only use the returned pointer while holding the corresponding [BorrowRef],
1252    /// otherwise there is no protection against mutable aliasing of the underlying data.
1253    #[track_caller]
1254    #[allow(unused)]
1255    pub unsafe fn borrow_unsafe(&self) -> (NonNull<T>, BorrowRef<'_>) {
1256        match self.try_borrow() {
1257            Ok(b) => (b.value, b.into_borrow_ref()),
1258            Err(err) => panic_aliasing_violation(err),
1259        }
1260    }
1261
1262    /// Construct a mutable borrow of this [RawEntity], returning the raw borrow components.
1263    ///
1264    /// # Safety
1265    ///
1266    /// Callers may only use the returned pointer while holding the corresponding [BorrowRefMut],
1267    /// otherwise there is no protection against mutable aliasing of the underlying data.
1268    #[track_caller]
1269    pub unsafe fn borrow_mut_unsafe(&self) -> (NonNull<T>, BorrowRefMut<'_>) {
1270        match self.try_borrow_mut() {
1271            Ok(b) => (b.value, b.into_borrow_ref_mut()),
1272            Err(err) => panic_aliasing_violation(err),
1273        }
1274    }
1275
1276    #[track_caller]
1277    #[inline]
1278    pub fn borrow(&self) -> EntityRef<'_, T> {
1279        match self.try_borrow() {
1280            Ok(b) => b,
1281            Err(err) => panic_aliasing_violation(err),
1282        }
1283    }
1284
1285    #[inline]
1286    #[track_caller]
1287    pub fn try_borrow(&self) -> Result<EntityRef<'_, T>, AliasingViolationError> {
1288        match BorrowRef::new(&self.borrow) {
1289            Some(b) => {
1290                #[cfg(debug_assertions)]
1291                {
1292                    // `borrowed_at` is always the *first* active borrow
1293                    if b.borrow.get() == BorrowFlag(1) {
1294                        self.borrowed_at.set(Some(core::panic::Location::caller()));
1295                    }
1296                }
1297
1298                // SAFETY: `BorrowRef` ensures that there is only immutable access to the value
1299                // while borrowed.
1300                let value = unsafe { NonNull::new_unchecked(self.cell.get()) };
1301                Ok(EntityRef { value, borrow: b })
1302            }
1303            None => Err(AliasingViolationError {
1304                #[cfg(debug_assertions)]
1305                location: self.borrowed_at.get().unwrap(),
1306                kind: AliasingViolationKind::Immutable,
1307            }),
1308        }
1309    }
1310
1311    #[inline]
1312    #[track_caller]
1313    pub fn borrow_mut(&self) -> EntityMut<'_, T> {
1314        match self.try_borrow_mut() {
1315            Ok(b) => b,
1316            Err(err) => panic_aliasing_violation(err),
1317        }
1318    }
1319
1320    #[inline]
1321    #[track_caller]
1322    pub fn try_borrow_mut(&self) -> Result<EntityMut<'_, T>, AliasingViolationError> {
1323        match BorrowRefMut::new(&self.borrow) {
1324            Some(b) => {
1325                #[cfg(debug_assertions)]
1326                {
1327                    self.borrowed_at.set(Some(core::panic::Location::caller()));
1328                }
1329
1330                // SAFETY: `BorrowRefMut` guarantees unique access.
1331                let value = unsafe { NonNull::new_unchecked(self.cell.get()) };
1332                Ok(EntityMut {
1333                    value,
1334                    borrow: b,
1335                    _marker: core::marker::PhantomData,
1336                })
1337            }
1338            None => Err(AliasingViolationError {
1339                // If a borrow occurred, then we must already have an outstanding borrow,
1340                // so `borrowed_at` will be `Some`
1341                #[cfg(debug_assertions)]
1342                location: self.borrowed_at.get().unwrap(),
1343                kind: AliasingViolationKind::Mutable,
1344            }),
1345        }
1346    }
1347}
1348
1349#[doc(hidden)]
1350pub struct BorrowRef<'b> {
1351    borrow: &'b Cell<BorrowFlag>,
1352}
1353impl<'b> BorrowRef<'b> {
1354    #[inline]
1355    fn new(borrow: &'b Cell<BorrowFlag>) -> Option<Self> {
1356        let b = borrow.get().wrapping_add(1);
1357        if !b.is_reading() {
1358            // Incrementing borrow can result in a non-reading value (<= 0) in these cases:
1359            // 1. It was < 0, i.e. there are writing borrows, so we can't allow a read borrow due to
1360            //    Rust's reference aliasing rules
1361            // 2. It was isize::MAX (the max amount of reading borrows) and it overflowed into
1362            //    isize::MIN (the max amount of writing borrows) so we can't allow an additional
1363            //    read borrow because isize can't represent so many read borrows (this can only
1364            //    happen if you mem::forget more than a small constant amount of `EntityRef`s, which
1365            //    is not good practice)
1366            None
1367        } else {
1368            // Incrementing borrow can result in a reading value (> 0) in these cases:
1369            // 1. It was = 0, i.e. it wasn't borrowed, and we are taking the first read borrow
1370            // 2. It was > 0 and < isize::MAX, i.e. there were read borrows, and isize is large
1371            //    enough to represent having one more read borrow
1372            borrow.set(b);
1373            Some(Self { borrow })
1374        }
1375    }
1376
1377    /// Convert this immutable borrow into a mutable one, if it is the sole immutable borrow.
1378    pub fn try_into_mut(self) -> Result<BorrowRefMut<'b>, Self> {
1379        use core::mem::ManuallyDrop;
1380
1381        // Ensure we don't try to modify the borrow flag when this BorrowRef goes out of scope
1382        let this = ManuallyDrop::new(self);
1383        let b = this.borrow.get();
1384        debug_assert!(b.is_reading());
1385        if (b - 1).is_unused() {
1386            this.borrow.set(BorrowFlag::UNUSED - 1);
1387            Ok(BorrowRefMut {
1388                borrow: this.borrow,
1389            })
1390        } else {
1391            Err(ManuallyDrop::into_inner(this))
1392        }
1393    }
1394}
1395impl Drop for BorrowRef<'_> {
1396    #[inline]
1397    fn drop(&mut self) {
1398        let borrow = self.borrow.get();
1399        debug_assert!(borrow.is_reading());
1400        self.borrow.set(borrow - 1);
1401    }
1402}
1403impl Clone for BorrowRef<'_> {
1404    #[inline]
1405    fn clone(&self) -> Self {
1406        // Since this Ref exists, we know the borrow flag
1407        // is a reading borrow.
1408        let borrow = self.borrow.get();
1409        debug_assert!(borrow.is_reading());
1410        // Prevent the borrow counter from overflowing into
1411        // a writing borrow.
1412        assert!(borrow != BorrowFlag::MAX);
1413        self.borrow.set(borrow + 1);
1414        BorrowRef {
1415            borrow: self.borrow,
1416        }
1417    }
1418}
1419
1420#[doc(hidden)]
1421pub struct BorrowRefMut<'b> {
1422    borrow: &'b Cell<BorrowFlag>,
1423}
1424impl Drop for BorrowRefMut<'_> {
1425    #[inline]
1426    fn drop(&mut self) {
1427        let borrow = self.borrow.get();
1428        debug_assert!(borrow.is_writing());
1429        self.borrow.set(borrow + 1);
1430    }
1431}
1432impl<'b> BorrowRefMut<'b> {
1433    /// Consume this mutable borrow and convert it into a immutable one without releasing it
1434    pub fn into_borrow_ref(self) -> BorrowRef<'b> {
1435        let borrow = self.borrow;
1436        debug_assert!(borrow.get().is_writing());
1437        borrow.set(borrow.get() + 2);
1438        core::mem::forget(self);
1439        BorrowRef { borrow }
1440    }
1441
1442    #[inline]
1443    fn new(borrow: &'b Cell<BorrowFlag>) -> Option<Self> {
1444        // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
1445        // mutable reference, and so there must currently be no existing
1446        // references. Thus, while clone increments the mutable refcount, here
1447        // we explicitly only allow going from UNUSED to UNUSED - 1.
1448        match borrow.get() {
1449            BorrowFlag::UNUSED => {
1450                borrow.set(BorrowFlag::UNUSED - 1);
1451                Some(Self { borrow })
1452            }
1453            _ => None,
1454        }
1455    }
1456
1457    // Clones a `BorrowRefMut`.
1458    //
1459    // This is only valid if each `BorrowRefMut` is used to track a mutable
1460    // reference to a distinct, nonoverlapping range of the original object.
1461    // This isn't in a Clone impl so that code doesn't call this implicitly.
1462    #[inline]
1463    fn clone(&self) -> Self {
1464        let borrow = self.borrow.get();
1465        debug_assert!(borrow.is_writing());
1466        // Prevent the borrow counter from underflowing.
1467        assert!(borrow != BorrowFlag::MIN);
1468        self.borrow.set(borrow - 1);
1469        Self {
1470            borrow: self.borrow,
1471        }
1472    }
1473}
1474
1475/// Positive values represent the number of outstanding immutable borrows, while negative values
1476/// represent the number of outstanding mutable borrows. Multiple mutable borrows can only be
1477/// active simultaneously if they refer to distinct, non-overlapping components of an entity.
1478#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
1479#[repr(transparent)]
1480struct BorrowFlag(isize);
1481impl BorrowFlag {
1482    const MAX: Self = Self(isize::MAX);
1483    const MIN: Self = Self(isize::MIN);
1484    const UNUSED: Self = Self(0);
1485
1486    #[allow(unused)]
1487    pub fn is_unused(&self) -> bool {
1488        self.0 == Self::UNUSED.0
1489    }
1490
1491    pub fn is_writing(&self) -> bool {
1492        self.0 < Self::UNUSED.0
1493    }
1494
1495    pub fn is_reading(&self) -> bool {
1496        self.0 > Self::UNUSED.0
1497    }
1498
1499    #[inline]
1500    pub const fn wrapping_add(self, rhs: isize) -> Self {
1501        Self(self.0.wrapping_add(rhs))
1502    }
1503}
1504impl core::ops::Add<isize> for BorrowFlag {
1505    type Output = BorrowFlag;
1506
1507    #[inline]
1508    fn add(self, rhs: isize) -> Self::Output {
1509        Self(self.0 + rhs)
1510    }
1511}
1512impl core::ops::Sub<isize> for BorrowFlag {
1513    type Output = BorrowFlag;
1514
1515    #[inline]
1516    fn sub(self, rhs: isize) -> Self::Output {
1517        Self(self.0 - rhs)
1518    }
1519}
1520
1521// This ensures the panicking code is outlined from `borrow` and `borrow_mut` for `EntityObj`.
1522#[cfg_attr(not(panic = "abort"), inline(never))]
1523#[track_caller]
1524#[cold]
1525fn panic_aliasing_violation(err: AliasingViolationError) -> ! {
1526    panic!("{err:?}")
1527}