Path: blob/main/crates/bevy_ecs/src/storage/table/column.rs
6609 views
use super::*;1use crate::{2change_detection::MaybeLocation,3component::TickCells,4storage::{blob_array::BlobArray, thin_array_ptr::ThinArrayPtr},5};6use alloc::vec::Vec;7use bevy_ptr::PtrMut;8use core::panic::Location;910/// Very similar to a normal [`Column`], but with the capacities and lengths cut out for performance reasons.11///12/// This type is used by [`Table`], because all of the capacities and lengths of the [`Table`]'s columns must match.13///14/// Like many other low-level storage types, [`ThinColumn`] has a limited and highly unsafe15/// interface. It's highly advised to use higher level types and their safe abstractions16/// instead of working directly with [`ThinColumn`].17pub struct ThinColumn {18pub(super) data: BlobArray,19pub(super) added_ticks: ThinArrayPtr<UnsafeCell<Tick>>,20pub(super) changed_ticks: ThinArrayPtr<UnsafeCell<Tick>>,21pub(super) changed_by: MaybeLocation<ThinArrayPtr<UnsafeCell<&'static Location<'static>>>>,22}2324impl ThinColumn {25/// Create a new [`ThinColumn`] with the given `capacity`.26pub fn with_capacity(component_info: &ComponentInfo, capacity: usize) -> Self {27Self {28// SAFETY: The components stored in this columns will match the information in `component_info`29data: unsafe {30BlobArray::with_capacity(component_info.layout(), component_info.drop(), capacity)31},32added_ticks: ThinArrayPtr::with_capacity(capacity),33changed_ticks: ThinArrayPtr::with_capacity(capacity),34changed_by: MaybeLocation::new_with(|| ThinArrayPtr::with_capacity(capacity)),35}36}3738/// Swap-remove and drop the removed element, but the component at `row` must not be the last element.39///40/// # Safety41/// - `row.as_usize()` < `len`42/// - `last_element_index` = `len - 1`43/// - `last_element_index` != `row.as_usize()`44/// - The caller should update the `len` to `len - 1`, or immediately initialize another element in the `last_element_index`45pub(crate) unsafe fn swap_remove_and_drop_unchecked_nonoverlapping(46&mut self,47last_element_index: usize,48row: TableRow,49) {50self.data51.swap_remove_and_drop_unchecked_nonoverlapping(row.index(), last_element_index);52self.added_ticks53.swap_remove_unchecked_nonoverlapping(row.index(), last_element_index);54self.changed_ticks55.swap_remove_unchecked_nonoverlapping(row.index(), last_element_index);56self.changed_by.as_mut().map(|changed_by| {57changed_by.swap_remove_unchecked_nonoverlapping(row.index(), last_element_index);58});59}6061/// Swap-remove and drop the removed element.62///63/// # Safety64/// - `last_element_index` must be the index of the last element—stored in the highest place in memory.65/// - `row.as_usize()` <= `last_element_index`66/// - The caller should update the their saved length to reflect the change (decrement it by 1).67pub(crate) unsafe fn swap_remove_and_drop_unchecked(68&mut self,69last_element_index: usize,70row: TableRow,71) {72self.data73.swap_remove_and_drop_unchecked(row.index(), last_element_index);74self.added_ticks75.swap_remove_and_drop_unchecked(row.index(), last_element_index);76self.changed_ticks77.swap_remove_and_drop_unchecked(row.index(), last_element_index);78self.changed_by.as_mut().map(|changed_by| {79changed_by.swap_remove_and_drop_unchecked(row.index(), last_element_index);80});81}8283/// Swap-remove and forget the removed element.84///85/// # Safety86/// - `last_element_index` must be the index of the last element—stored in the highest place in memory.87/// - `row.as_usize()` <= `last_element_index`88/// - The caller should update the their saved length to reflect the change (decrement it by 1).89pub(crate) unsafe fn swap_remove_and_forget_unchecked(90&mut self,91last_element_index: usize,92row: TableRow,93) {94let _ = self95.data96.swap_remove_unchecked(row.index(), last_element_index);97self.added_ticks98.swap_remove_unchecked(row.index(), last_element_index);99self.changed_ticks100.swap_remove_unchecked(row.index(), last_element_index);101self.changed_by102.as_mut()103.map(|changed_by| changed_by.swap_remove_unchecked(row.index(), last_element_index));104}105106/// Call [`realloc`](std::alloc::realloc) to expand / shrink the memory allocation for this [`ThinColumn`]107///108/// # Safety109/// - `current_capacity` must be the current capacity of this column (the capacity of `self.data`, `self.added_ticks`, `self.changed_tick`)110/// - The caller should make sure their saved `capacity` value is updated to `new_capacity` after this operation.111pub(crate) unsafe fn realloc(112&mut self,113current_capacity: NonZeroUsize,114new_capacity: NonZeroUsize,115) {116self.data.realloc(current_capacity, new_capacity);117self.added_ticks.realloc(current_capacity, new_capacity);118self.changed_ticks.realloc(current_capacity, new_capacity);119self.changed_by120.as_mut()121.map(|changed_by| changed_by.realloc(current_capacity, new_capacity));122}123124/// Call [`alloc`](std::alloc::alloc) to allocate memory for this [`ThinColumn`]125/// The caller should make sure their saved `capacity` value is updated to `new_capacity` after this operation.126pub(crate) fn alloc(&mut self, new_capacity: NonZeroUsize) {127self.data.alloc(new_capacity);128self.added_ticks.alloc(new_capacity);129self.changed_ticks.alloc(new_capacity);130self.changed_by131.as_mut()132.map(|changed_by| changed_by.alloc(new_capacity));133}134135/// Writes component data to the column at the given row.136/// Assumes the slot is uninitialized, drop is not called.137/// To overwrite existing initialized value, use [`Self::replace`] instead.138///139/// # Safety140/// - `row.as_usize()` must be in bounds.141/// - `comp_ptr` holds a component that matches the `component_id`142#[inline]143pub(crate) unsafe fn initialize(144&mut self,145row: TableRow,146data: OwningPtr<'_>,147tick: Tick,148caller: MaybeLocation,149) {150self.data.initialize_unchecked(row.index(), data);151*self.added_ticks.get_unchecked_mut(row.index()).get_mut() = tick;152*self.changed_ticks.get_unchecked_mut(row.index()).get_mut() = tick;153self.changed_by154.as_mut()155.map(|changed_by| changed_by.get_unchecked_mut(row.index()).get_mut())156.assign(caller);157}158159/// Writes component data to the column at given row. Assumes the slot is initialized, drops the previous value.160///161/// # Safety162/// - `row.as_usize()` must be in bounds.163/// - `data` holds a component that matches the `component_id`164#[inline]165pub(crate) unsafe fn replace(166&mut self,167row: TableRow,168data: OwningPtr<'_>,169change_tick: Tick,170caller: MaybeLocation,171) {172self.data.replace_unchecked(row.index(), data);173*self.changed_ticks.get_unchecked_mut(row.index()).get_mut() = change_tick;174self.changed_by175.as_mut()176.map(|changed_by| changed_by.get_unchecked_mut(row.index()).get_mut())177.assign(caller);178}179180/// Removes the element from `other` at `src_row` and inserts it181/// into the current column to initialize the values at `dst_row`.182/// Does not do any bounds checking.183///184/// # Safety185/// - `other` must have the same data layout as `self`186/// - `src_row` must be in bounds for `other`187/// - `dst_row` must be in bounds for `self`188/// - `other[src_row]` must be initialized to a valid value.189/// - `self[dst_row]` must not be initialized yet.190#[inline]191pub(crate) unsafe fn initialize_from_unchecked(192&mut self,193other: &mut ThinColumn,194other_last_element_index: usize,195src_row: TableRow,196dst_row: TableRow,197) {198debug_assert!(self.data.layout() == other.data.layout());199// Init the data200let src_val = other201.data202.swap_remove_unchecked(src_row.index(), other_last_element_index);203self.data.initialize_unchecked(dst_row.index(), src_val);204// Init added_ticks205let added_tick = other206.added_ticks207.swap_remove_unchecked(src_row.index(), other_last_element_index);208self.added_ticks209.initialize_unchecked(dst_row.index(), added_tick);210// Init changed_ticks211let changed_tick = other212.changed_ticks213.swap_remove_unchecked(src_row.index(), other_last_element_index);214self.changed_ticks215.initialize_unchecked(dst_row.index(), changed_tick);216self.changed_by.as_mut().zip(other.changed_by.as_mut()).map(217|(self_changed_by, other_changed_by)| {218let changed_by = other_changed_by219.swap_remove_unchecked(src_row.index(), other_last_element_index);220self_changed_by.initialize_unchecked(dst_row.index(), changed_by);221},222);223}224225/// Call [`Tick::check_tick`] on all of the ticks stored in this column.226///227/// # Safety228/// `len` is the actual length of this column229#[inline]230pub(crate) unsafe fn check_change_ticks(&mut self, len: usize, check: CheckChangeTicks) {231for i in 0..len {232// SAFETY:233// - `i` < `len`234// we have a mutable reference to `self`235unsafe { self.added_ticks.get_unchecked_mut(i) }236.get_mut()237.check_tick(check);238// SAFETY:239// - `i` < `len`240// we have a mutable reference to `self`241unsafe { self.changed_ticks.get_unchecked_mut(i) }242.get_mut()243.check_tick(check);244}245}246247/// Clear all the components from this column.248///249/// # Safety250/// - `len` must match the actual length of the column251/// - The caller must not use the elements this column's data until [`initializing`](Self::initialize) it again (set `len` to 0).252pub(crate) unsafe fn clear(&mut self, len: usize) {253self.added_ticks.clear_elements(len);254self.changed_ticks.clear_elements(len);255self.data.clear(len);256self.changed_by257.as_mut()258.map(|changed_by| changed_by.clear_elements(len));259}260261/// Because this method needs parameters, it can't be the implementation of the `Drop` trait.262/// The owner of this [`ThinColumn`] must call this method with the correct information.263///264/// # Safety265/// - `len` is indeed the length of the column266/// - `cap` is indeed the capacity of the column267/// - the data stored in `self` will never be used again268pub(crate) unsafe fn drop(&mut self, cap: usize, len: usize) {269self.added_ticks.drop(cap, len);270self.changed_ticks.drop(cap, len);271self.data.drop(cap, len);272self.changed_by273.as_mut()274.map(|changed_by| changed_by.drop(cap, len));275}276277/// Drops the last component in this column.278///279/// # Safety280/// - `last_element_index` is indeed the index of the last element281/// - the data stored in `last_element_index` will never be used unless properly initialized again.282pub(crate) unsafe fn drop_last_component(&mut self, last_element_index: usize) {283core::ptr::drop_in_place(self.added_ticks.get_unchecked_raw(last_element_index));284core::ptr::drop_in_place(self.changed_ticks.get_unchecked_raw(last_element_index));285self.changed_by.as_mut().map(|changed_by| {286core::ptr::drop_in_place(changed_by.get_unchecked_raw(last_element_index));287});288self.data.drop_last_element(last_element_index);289}290291/// Get a slice to the data stored in this [`ThinColumn`].292///293/// # Safety294/// - `T` must match the type of data that's stored in this [`ThinColumn`]295/// - `len` must match the actual length of this column (number of elements stored)296pub unsafe fn get_data_slice<T>(&self, len: usize) -> &[UnsafeCell<T>] {297self.data.get_sub_slice(len)298}299300/// Get a slice to the added [`ticks`](Tick) in this [`ThinColumn`].301///302/// # Safety303/// - `len` must match the actual length of this column (number of elements stored)304pub unsafe fn get_added_ticks_slice(&self, len: usize) -> &[UnsafeCell<Tick>] {305self.added_ticks.as_slice(len)306}307308/// Get a slice to the changed [`ticks`](Tick) in this [`ThinColumn`].309///310/// # Safety311/// - `len` must match the actual length of this column (number of elements stored)312pub unsafe fn get_changed_ticks_slice(&self, len: usize) -> &[UnsafeCell<Tick>] {313self.changed_ticks.as_slice(len)314}315316/// Get a slice to the calling locations that last changed each value in this [`ThinColumn`]317///318/// # Safety319/// - `len` must match the actual length of this column (number of elements stored)320pub unsafe fn get_changed_by_slice(321&self,322len: usize,323) -> MaybeLocation<&[UnsafeCell<&'static Location<'static>>]> {324self.changed_by325.as_ref()326.map(|changed_by| changed_by.as_slice(len))327}328}329330/// A type-erased contiguous container for data of a homogeneous type.331///332/// Conceptually, a [`Column`] is very similar to a type-erased `Vec<T>`.333/// It also stores the change detection ticks for its components, kept in two separate334/// contiguous buffers internally. An element shares its data across these buffers by using the335/// same index (i.e. the entity at row 3 has it's data at index 3 and its change detection ticks at index 3).336///337/// Like many other low-level storage types, [`Column`] has a limited and highly unsafe338/// interface. It's highly advised to use higher level types and their safe abstractions339/// instead of working directly with [`Column`].340#[derive(Debug)]341pub struct Column {342pub(super) data: BlobVec,343pub(super) added_ticks: Vec<UnsafeCell<Tick>>,344pub(super) changed_ticks: Vec<UnsafeCell<Tick>>,345changed_by: MaybeLocation<Vec<UnsafeCell<&'static Location<'static>>>>,346}347348impl Column {349/// Constructs a new [`Column`], configured with a component's layout and an initial `capacity`.350#[inline]351pub(crate) fn with_capacity(component_info: &ComponentInfo, capacity: usize) -> Self {352Column {353// SAFETY: component_info.drop() is valid for the types that will be inserted.354data: unsafe { BlobVec::new(component_info.layout(), component_info.drop(), capacity) },355added_ticks: Vec::with_capacity(capacity),356changed_ticks: Vec::with_capacity(capacity),357changed_by: MaybeLocation::new_with(|| Vec::with_capacity(capacity)),358}359}360361/// Fetches the [`Layout`] for the underlying type.362#[inline]363pub fn item_layout(&self) -> Layout {364self.data.layout()365}366367/// Writes component data to the column at given row.368/// Assumes the slot is initialized, calls drop.369///370/// # Safety371/// Assumes data has already been allocated for the given row.372#[inline]373pub(crate) unsafe fn replace(374&mut self,375row: TableRow,376data: OwningPtr<'_>,377change_tick: Tick,378caller: MaybeLocation,379) {380debug_assert!(row.index() < self.len());381self.data.replace_unchecked(row.index(), data);382*self.changed_ticks.get_unchecked_mut(row.index()).get_mut() = change_tick;383self.changed_by384.as_mut()385.map(|changed_by| changed_by.get_unchecked_mut(row.index()).get_mut())386.assign(caller);387}388389/// Gets the current number of elements stored in the column.390#[inline]391pub fn len(&self) -> usize {392self.data.len()393}394395/// Checks if the column is empty. Returns `true` if there are no elements, `false` otherwise.396#[inline]397pub fn is_empty(&self) -> bool {398self.data.is_empty()399}400401/// Removes an element from the [`Column`].402///403/// - The value will be dropped if it implements [`Drop`].404/// - This does not preserve ordering, but is O(1).405/// - This does not do any bounds checking.406/// - The element is replaced with the last element in the [`Column`].407///408/// # Safety409/// `row` must be within the range `[0, self.len())`.410#[inline]411pub(crate) unsafe fn swap_remove_unchecked(&mut self, row: TableRow) {412self.data.swap_remove_and_drop_unchecked(row.index());413self.added_ticks.swap_remove(row.index());414self.changed_ticks.swap_remove(row.index());415self.changed_by416.as_mut()417.map(|changed_by| changed_by.swap_remove(row.index()));418}419420/// Removes an element from the [`Column`] and returns it and its change detection ticks.421/// This does not preserve ordering, but is O(1) and does not do any bounds checking.422///423/// The element is replaced with the last element in the [`Column`].424///425/// It's the caller's responsibility to ensure that the removed value is dropped or used.426/// Failure to do so may result in resources not being released (i.e. files handles not being427/// released, memory leaks, etc.)428///429/// # Safety430/// `row` must be within the range `[0, self.len())`.431#[inline]432#[must_use = "The returned pointer should be used to dropped the removed component"]433pub(crate) unsafe fn swap_remove_and_forget_unchecked(434&mut self,435row: TableRow,436) -> (OwningPtr<'_>, ComponentTicks, MaybeLocation) {437let data = self.data.swap_remove_and_forget_unchecked(row.index());438let added = self.added_ticks.swap_remove(row.index()).into_inner();439let changed = self.changed_ticks.swap_remove(row.index()).into_inner();440let caller = self441.changed_by442.as_mut()443.map(|changed_by| changed_by.swap_remove(row.index()).into_inner());444(data, ComponentTicks { added, changed }, caller)445}446447/// Pushes a new value onto the end of the [`Column`].448///449/// # Safety450/// `ptr` must point to valid data of this column's component type451pub(crate) unsafe fn push(452&mut self,453ptr: OwningPtr<'_>,454ticks: ComponentTicks,455caller: MaybeLocation,456) {457self.data.push(ptr);458self.added_ticks.push(UnsafeCell::new(ticks.added));459self.changed_ticks.push(UnsafeCell::new(ticks.changed));460self.changed_by461.as_mut()462.zip(caller)463.map(|(changed_by, caller)| changed_by.push(UnsafeCell::new(caller)));464}465466/// Fetches the data pointer to the first element of the [`Column`].467///468/// The pointer is type erased, so using this function to fetch anything469/// other than the first element will require computing the offset using470/// [`Column::item_layout`].471#[inline]472pub fn get_data_ptr(&self) -> Ptr<'_> {473self.data.get_ptr()474}475476/// Fetches the slice to the [`Column`]'s data cast to a given type.477///478/// Note: The values stored within are [`UnsafeCell`].479/// Users of this API must ensure that accesses to each individual element480/// adhere to the safety invariants of [`UnsafeCell`].481///482/// # Safety483/// The type `T` must be the type of the items in this column.484pub unsafe fn get_data_slice<T>(&self) -> &[UnsafeCell<T>] {485self.data.get_slice()486}487488/// Fetches the slice to the [`Column`]'s "added" change detection ticks.489///490/// Note: The values stored within are [`UnsafeCell`].491/// Users of this API must ensure that accesses to each individual element492/// adhere to the safety invariants of [`UnsafeCell`].493#[inline]494pub fn get_added_ticks_slice(&self) -> &[UnsafeCell<Tick>] {495&self.added_ticks496}497498/// Fetches the slice to the [`Column`]'s "changed" change detection ticks.499///500/// Note: The values stored within are [`UnsafeCell`].501/// Users of this API must ensure that accesses to each individual element502/// adhere to the safety invariants of [`UnsafeCell`].503#[inline]504pub fn get_changed_ticks_slice(&self) -> &[UnsafeCell<Tick>] {505&self.changed_ticks506}507508/// Fetches a reference to the data and change detection ticks at `row`.509///510/// Returns `None` if `row` is out of bounds.511#[inline]512pub fn get(&self, row: TableRow) -> Option<(Ptr<'_>, TickCells<'_>)> {513(row.index() < self.data.len())514// SAFETY: The row is length checked before fetching the pointer. This is being515// accessed through a read-only reference to the column.516.then(|| unsafe {517(518self.data.get_unchecked(row.index()),519TickCells {520added: self.added_ticks.get_unchecked(row.index()),521changed: self.changed_ticks.get_unchecked(row.index()),522},523)524})525}526527/// Fetches a read-only reference to the data at `row`.528///529/// Returns `None` if `row` is out of bounds.530#[inline]531pub fn get_data(&self, row: TableRow) -> Option<Ptr<'_>> {532(row.index() < self.data.len()).then(|| {533// SAFETY: The row is length checked before fetching the pointer. This is being534// accessed through a read-only reference to the column.535unsafe { self.data.get_unchecked(row.index()) }536})537}538539/// Fetches a read-only reference to the data at `row`. Unlike [`Column::get`] this does not540/// do any bounds checking.541///542/// # Safety543/// - `row` must be within the range `[0, self.len())`.544/// - no other mutable reference to the data of the same row can exist at the same time545#[inline]546pub unsafe fn get_data_unchecked(&self, row: TableRow) -> Ptr<'_> {547debug_assert!(row.index() < self.data.len());548self.data.get_unchecked(row.index())549}550551/// Fetches a mutable reference to the data at `row`.552///553/// Returns `None` if `row` is out of bounds.554#[inline]555pub fn get_data_mut(&mut self, row: TableRow) -> Option<PtrMut<'_>> {556(row.index() < self.data.len()).then(|| {557// SAFETY: The row is length checked before fetching the pointer. This is being558// accessed through an exclusive reference to the column.559unsafe { self.data.get_unchecked_mut(row.index()) }560})561}562563/// Fetches the "added" change detection tick for the value at `row`.564///565/// Returns `None` if `row` is out of bounds.566///567/// Note: The values stored within are [`UnsafeCell`].568/// Users of this API must ensure that accesses to each individual element569/// adhere to the safety invariants of [`UnsafeCell`].570#[inline]571pub fn get_added_tick(&self, row: TableRow) -> Option<&UnsafeCell<Tick>> {572self.added_ticks.get(row.index())573}574575/// Fetches the "changed" change detection tick for the value at `row`.576///577/// Returns `None` if `row` is out of bounds.578///579/// Note: The values stored within are [`UnsafeCell`].580/// Users of this API must ensure that accesses to each individual element581/// adhere to the safety invariants of [`UnsafeCell`].582#[inline]583pub fn get_changed_tick(&self, row: TableRow) -> Option<&UnsafeCell<Tick>> {584self.changed_ticks.get(row.index())585}586587/// Fetches the change detection ticks for the value at `row`.588///589/// Returns `None` if `row` is out of bounds.590#[inline]591pub fn get_ticks(&self, row: TableRow) -> Option<ComponentTicks> {592if row.index() < self.data.len() {593// SAFETY: The size of the column has already been checked.594Some(unsafe { self.get_ticks_unchecked(row) })595} else {596None597}598}599600/// Fetches the "added" change detection tick for the value at `row`. Unlike [`Column::get_added_tick`]601/// this function does not do any bounds checking.602///603/// # Safety604/// `row` must be within the range `[0, self.len())`.605#[inline]606pub unsafe fn get_added_tick_unchecked(&self, row: TableRow) -> &UnsafeCell<Tick> {607debug_assert!(row.index() < self.added_ticks.len());608self.added_ticks.get_unchecked(row.index())609}610611/// Fetches the "changed" change detection tick for the value at `row`. Unlike [`Column::get_changed_tick`]612/// this function does not do any bounds checking.613///614/// # Safety615/// `row` must be within the range `[0, self.len())`.616#[inline]617pub unsafe fn get_changed_tick_unchecked(&self, row: TableRow) -> &UnsafeCell<Tick> {618debug_assert!(row.index() < self.changed_ticks.len());619self.changed_ticks.get_unchecked(row.index())620}621622/// Fetches the change detection ticks for the value at `row`. Unlike [`Column::get_ticks`]623/// this function does not do any bounds checking.624///625/// # Safety626/// `row` must be within the range `[0, self.len())`.627#[inline]628pub unsafe fn get_ticks_unchecked(&self, row: TableRow) -> ComponentTicks {629debug_assert!(row.index() < self.added_ticks.len());630debug_assert!(row.index() < self.changed_ticks.len());631ComponentTicks {632added: self.added_ticks.get_unchecked(row.index()).read(),633changed: self.changed_ticks.get_unchecked(row.index()).read(),634}635}636637/// Clears the column, removing all values.638///639/// Note that this function has no effect on the allocated capacity of the [`Column`]>640pub fn clear(&mut self) {641self.data.clear();642self.added_ticks.clear();643self.changed_ticks.clear();644self.changed_by.as_mut().map(Vec::clear);645}646647#[inline]648pub(crate) fn check_change_ticks(&mut self, check: CheckChangeTicks) {649for component_ticks in &mut self.added_ticks {650component_ticks.get_mut().check_tick(check);651}652for component_ticks in &mut self.changed_ticks {653component_ticks.get_mut().check_tick(check);654}655}656657/// Fetches the calling location that last changed the value at `row`.658///659/// Returns `None` if `row` is out of bounds.660///661/// Note: The values stored within are [`UnsafeCell`].662/// Users of this API must ensure that accesses to each individual element663/// adhere to the safety invariants of [`UnsafeCell`].664#[inline]665pub fn get_changed_by(666&self,667row: TableRow,668) -> MaybeLocation<Option<&UnsafeCell<&'static Location<'static>>>> {669self.changed_by670.as_ref()671.map(|changed_by| changed_by.get(row.index()))672}673674/// Fetches the calling location that last changed the value at `row`.675///676/// Unlike [`Column::get_changed_by`] this function does not do any bounds checking.677///678/// # Safety679/// `row` must be within the range `[0, self.len())`.680#[inline]681pub unsafe fn get_changed_by_unchecked(682&self,683row: TableRow,684) -> MaybeLocation<&UnsafeCell<&'static Location<'static>>> {685self.changed_by.as_ref().map(|changed_by| {686debug_assert!(row.index() < changed_by.len());687changed_by.get_unchecked(row.index())688})689}690691/// Returns the drop function for elements of the column,692/// or `None` if they don't need to be dropped.693#[inline]694pub fn get_drop(&self) -> Option<unsafe fn(OwningPtr<'_>)> {695self.data.get_drop()696}697}698699700