gpui: Remove some unnecessary unsafe code (#40483)

Release Notes:

- N/A *or* Added/Fixed/Improved ...
This commit is contained in:
Lukas Wirth 2025-10-17 14:20:13 +02:00 committed by GitHub
parent eb3f9b0ea3
commit b59a3bbd49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 76 additions and 92 deletions

1
Cargo.lock generated
View file

@ -7390,6 +7390,7 @@ dependencies = [
"parking",
"parking_lot",
"pathfinder_geometry",
"pin-project",
"postage",
"pretty_assertions",
"profiling",

View file

@ -135,6 +135,7 @@ waker-fn = "1.2.0"
lyon = "1.0"
workspace-hack.workspace = true
libc.workspace = true
pin-project = "1.1.10"
[target.'cfg(target_os = "macos")'.dependencies]
block = "0.1"

View file

@ -378,11 +378,9 @@ pub struct Entity<T> {
#[deref]
#[deref_mut]
pub(crate) any_entity: AnyEntity,
pub(crate) entity_type: PhantomData<T>,
pub(crate) entity_type: PhantomData<fn(T) -> T>,
}
unsafe impl<T> Send for Entity<T> {}
unsafe impl<T> Sync for Entity<T> {}
impl<T> Sealed for Entity<T> {}
impl<T: 'static> Entity<T> {
@ -657,7 +655,7 @@ pub struct WeakEntity<T> {
#[deref]
#[deref_mut]
any_entity: AnyWeakEntity,
entity_type: PhantomData<T>,
entity_type: PhantomData<fn(T) -> T>,
}
impl<T> std::fmt::Debug for WeakEntity<T> {
@ -669,9 +667,6 @@ impl<T> std::fmt::Debug for WeakEntity<T> {
}
}
unsafe impl<T> Send for WeakEntity<T> {}
unsafe impl<T> Sync for WeakEntity<T> {}
impl<T> Clone for WeakEntity<T> {
fn clone(&self) -> Self {
Self {

View file

@ -888,7 +888,9 @@ impl VisualTestContext {
// safety: on_quit will be called after the test has finished.
// the executor will ensure that all tasks related to the test have stopped.
// so there is no way for cx to be accessed after on_quit is called.
let cx = Box::leak(unsafe { Box::from_raw(ptr) });
// todo: This is unsound under stacked borrows (also tree borrows probably?)
// the mutable reference invalidates `ptr` which is later used in the closure
let cx = unsafe { &mut *ptr };
cx.on_quit(move || unsafe {
drop(Box::from_raw(ptr));
});

View file

@ -15,9 +15,7 @@ struct ArenaElement {
impl Drop for ArenaElement {
#[inline(always)]
fn drop(&mut self) {
unsafe {
(self.drop)(self.value);
}
unsafe { (self.drop)(self.value) };
}
}
@ -40,33 +38,29 @@ impl Drop for Chunk {
impl Chunk {
fn new(chunk_size: NonZeroUsize) -> Self {
unsafe {
// this only fails if chunk_size is unreasonably huge
let layout = alloc::Layout::from_size_align(chunk_size.get(), 1).unwrap();
let start = alloc::alloc(layout);
if start.is_null() {
handle_alloc_error(layout);
}
let end = start.add(chunk_size.get());
Self {
start,
end,
offset: start,
}
// this only fails if chunk_size is unreasonably huge
let layout = alloc::Layout::from_size_align(chunk_size.get(), 1).unwrap();
let start = unsafe { alloc::alloc(layout) };
if start.is_null() {
handle_alloc_error(layout);
}
let end = unsafe { start.add(chunk_size.get()) };
Self {
start,
end,
offset: start,
}
}
fn allocate(&mut self, layout: alloc::Layout) -> Option<NonNull<u8>> {
unsafe {
let aligned = self.offset.add(self.offset.align_offset(layout.align()));
let next = aligned.add(layout.size());
let aligned = unsafe { self.offset.add(self.offset.align_offset(layout.align())) };
let next = unsafe { aligned.add(layout.size()) };
if next <= self.end {
self.offset = next;
NonNull::new(aligned)
} else {
None
}
if next <= self.end {
self.offset = next;
NonNull::new(aligned)
} else {
None
}
}
@ -122,54 +116,48 @@ impl Arena {
where
F: FnOnce() -> T,
{
unsafe {
ptr::write(ptr, f());
}
unsafe { ptr::write(ptr, f()) };
}
unsafe fn drop<T>(ptr: *mut u8) {
unsafe {
std::ptr::drop_in_place(ptr.cast::<T>());
}
unsafe { std::ptr::drop_in_place(ptr.cast::<T>()) };
}
unsafe {
let layout = alloc::Layout::new::<T>();
let mut current_chunk = &mut self.chunks[self.current_chunk_index];
let ptr = if let Some(ptr) = current_chunk.allocate(layout) {
let layout = alloc::Layout::new::<T>();
let mut current_chunk = &mut self.chunks[self.current_chunk_index];
let ptr = if let Some(ptr) = current_chunk.allocate(layout) {
ptr.as_ptr()
} else {
self.current_chunk_index += 1;
if self.current_chunk_index >= self.chunks.len() {
self.chunks.push(Chunk::new(self.chunk_size));
assert_eq!(self.current_chunk_index, self.chunks.len() - 1);
log::trace!(
"increased element arena capacity to {}kb",
self.capacity() / 1024,
);
}
current_chunk = &mut self.chunks[self.current_chunk_index];
if let Some(ptr) = current_chunk.allocate(layout) {
ptr.as_ptr()
} else {
self.current_chunk_index += 1;
if self.current_chunk_index >= self.chunks.len() {
self.chunks.push(Chunk::new(self.chunk_size));
assert_eq!(self.current_chunk_index, self.chunks.len() - 1);
log::trace!(
"increased element arena capacity to {}kb",
self.capacity() / 1024,
);
}
current_chunk = &mut self.chunks[self.current_chunk_index];
if let Some(ptr) = current_chunk.allocate(layout) {
ptr.as_ptr()
} else {
panic!(
"Arena chunk_size of {} is too small to allocate {} bytes",
self.chunk_size,
layout.size()
);
}
};
inner_writer(ptr.cast(), f);
self.elements.push(ArenaElement {
value: ptr,
drop: drop::<T>,
});
ArenaBox {
ptr: ptr.cast(),
valid: self.valid.clone(),
panic!(
"Arena chunk_size of {} is too small to allocate {} bytes",
self.chunk_size,
layout.size()
);
}
};
unsafe { inner_writer(ptr.cast(), f) };
self.elements.push(ArenaElement {
value: ptr,
drop: drop::<T>,
});
ArenaBox {
ptr: ptr.cast(),
valid: self.valid.clone(),
}
}
}

View file

@ -525,9 +525,7 @@ where
"local task dropped by a thread that didn't spawn it. Task spawned at {}",
self.location
);
unsafe {
ManuallyDrop::drop(&mut self.inner);
}
unsafe { ManuallyDrop::drop(&mut self.inner) };
}
}

View file

@ -348,8 +348,6 @@ impl Debug for DisplayId {
}
}
unsafe impl Send for DisplayId {}
/// Which part of the window to resize
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResizeEdge {

View file

@ -69,9 +69,7 @@ impl TaffyLayoutEngine {
} else {
self.taffy
// This is safe because LayoutId is repr(transparent) to taffy::tree::NodeId.
.new_with_children(taffy_style, unsafe {
std::mem::transmute::<&[LayoutId], &[taffy::NodeId]>(children)
})
.new_with_children(taffy_style, LayoutId::to_taffy_slice(children))
.expect(EXPECT_MESSAGE)
.into()
}
@ -265,6 +263,13 @@ impl TaffyLayoutEngine {
#[repr(transparent)]
pub struct LayoutId(NodeId);
impl LayoutId {
fn to_taffy_slice(node_ids: &[Self]) -> &[taffy::NodeId] {
// SAFETY: LayoutId is repr(transparent) to taffy::tree::NodeId.
unsafe { std::mem::transmute::<&[LayoutId], &[taffy::NodeId]>(node_ids) }
}
}
impl std::hash::Hash for LayoutId {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
u64::from(self.0).hash(state);

View file

@ -83,8 +83,11 @@ impl<T: Future> FutureExt for T {
}
}
#[pin_project::pin_project]
pub struct WithTimeout<T> {
#[pin]
future: T,
#[pin]
timer: Task<()>,
}
@ -97,15 +100,11 @@ impl<T: Future> Future for WithTimeout<T> {
type Output = Result<T::Output, Timeout>;
fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> task::Poll<Self::Output> {
// SAFETY: the fields of Timeout are private and we never move the future ourselves
// And its already pinned since we are being polled (all futures need to be pinned to be polled)
let this = unsafe { &raw mut *self.get_unchecked_mut() };
let future = unsafe { Pin::new_unchecked(&mut (*this).future) };
let timer = unsafe { Pin::new_unchecked(&mut (*this).timer) };
let this = self.project();
if let task::Poll::Ready(output) = future.poll(cx) {
if let task::Poll::Ready(output) = this.future.poll(cx) {
task::Poll::Ready(Ok(output))
} else if timer.poll(cx).is_ready() {
} else if this.timer.poll(cx).is_ready() {
task::Poll::Ready(Err(Timeout))
} else {
task::Poll::Pending

View file

@ -4650,7 +4650,7 @@ pub struct WindowHandle<V> {
#[deref]
#[deref_mut]
pub(crate) any_handle: AnyWindowHandle,
state_type: PhantomData<V>,
state_type: PhantomData<fn(V) -> V>,
}
impl<V> Debug for WindowHandle<V> {
@ -4786,9 +4786,6 @@ impl<V: 'static> From<WindowHandle<V>> for AnyWindowHandle {
}
}
unsafe impl<V> Send for WindowHandle<V> {}
unsafe impl<V> Sync for WindowHandle<V> {}
/// A handle to a window with any root view type, which can be downcast to a window with a specific root view type.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct AnyWindowHandle {