trust + fix redraw bug

This commit is contained in:
2025-12-17 01:16:28 -05:00
parent 70ac0fbcb2
commit 7e6369029f
7 changed files with 38 additions and 32 deletions

View File

@@ -1,6 +1,9 @@
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
use crate::render::{MaskIdx, Primitive, PrimitiveHandle, PrimitiveInst, Primitives}; use crate::{
render::{MaskIdx, Primitive, PrimitiveHandle, PrimitiveInst, Primitives},
util::to_mut,
};
pub type LayerId = usize; pub type LayerId = usize;
@@ -176,8 +179,7 @@ impl<'a, T> Iterator for LayerIteratorMut<'a, T> {
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let i = self.inner.next()?; let i = self.inner.next()?;
// SAFETY: requires index iterator to work properly // SAFETY: requires index iterator to work properly
#[allow(mutable_transmutes)] let layer = unsafe { to_mut(&self.inner.vec[i].data) };
let layer = unsafe { std::mem::transmute::<&T, &mut T>(&self.inner.vec[i].data) };
Some((i, layer)) Some((i, layer))
} }
} }
@@ -186,8 +188,7 @@ impl<'a, T> DoubleEndedIterator for LayerIteratorMut<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> { fn next_back(&mut self) -> Option<Self::Item> {
let i = self.inner.next_back()?; let i = self.inner.next_back()?;
// SAFETY: requires index iterator to work properly // SAFETY: requires index iterator to work properly
#[allow(mutable_transmutes)] let layer = unsafe { to_mut(&self.inner.vec[i].data) };
let layer = unsafe { std::mem::transmute::<&T, &mut T>(&self.inner.vec[i].data) };
Some((i, layer)) Some((i, layer))
} }
} }

View File

@@ -1,6 +1,7 @@
use crate::{ use crate::{
ActiveData, Axis, Painter, SizeCtx, Ui, UiRegion, UiVec2, WidgetId, render::MaskIdx, ActiveData, Axis, Painter, SizeCtx, Ui, UiRegion, UiVec2, WidgetId,
util::HashSet, render::MaskIdx,
util::{HashSet, forget_ref},
}; };
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
@@ -30,9 +31,7 @@ impl<'a, State: 'static> DrawState<'a, State> {
/// will just return if so /// will just return if so
pub fn redraw(&mut self, id: WidgetId) { pub fn redraw(&mut self, id: WidgetId) {
self.widgets.needs_redraw.remove(&id); self.widgets.needs_redraw.remove(&id);
if self.draw_started.contains(&id) { self.draw_started.remove(&id);
return;
}
// check if parent depends on the desired size of this, if so then redraw it first // check if parent depends on the desired size of this, if so then redraw it first
for axis in [Axis::X, Axis::Y] { for axis in [Axis::X, Axis::Y] {
if let Some(&(outer, old)) = self.cache.size.axis_dyn(axis).get(&id) if let Some(&(outer, old)) = self.cache.size.axis_dyn(axis).get(&id)
@@ -202,11 +201,10 @@ impl<'a, State: 'static> DrawState<'a, State> {
*region = region.outside(&from).within(&to); *region = region.outside(&from).within(&to);
} }
active.region = active.region.outside(&from).within(&to); active.region = active.region.outside(&from).within(&to);
// children will not be changed, so this technically should not be needed // SAFETY: children cannot be recursive
// probably need unsafe let children = unsafe { forget_ref(&active.children) };
let children = active.children.clone();
for child in children { for child in children {
self.mov(child, from, to); self.mov(*child, from, to);
} }
} }

View File

@@ -1,4 +1,3 @@
mod typemap;
mod arena; mod arena;
mod borrow; mod borrow;
mod change; mod change;
@@ -6,9 +5,10 @@ mod id;
mod math; mod math;
mod refcount; mod refcount;
mod slot; mod slot;
mod trust;
mod typemap;
mod vec2; mod vec2;
pub use typemap::*;
pub use arena::*; pub use arena::*;
pub use borrow::*; pub use borrow::*;
pub use change::*; pub use change::*;
@@ -16,6 +16,8 @@ pub use id::*;
pub use math::*; pub use math::*;
pub use refcount::*; pub use refcount::*;
pub use slot::*; pub use slot::*;
pub use trust::*;
pub use typemap::*;
pub use vec2::*; pub use vec2::*;
pub type HashMap<K, V> = fxhash::FxHashMap<K, V>; pub type HashMap<K, V> = fxhash::FxHashMap<K, V>;

17
core/src/util/trust.rs Normal file
View File

@@ -0,0 +1,17 @@
#[allow(clippy::missing_safety_doc)]
pub unsafe fn forget_ref<'a, T>(x: &T) -> &'a T {
unsafe { std::mem::transmute::<&T, &T>(x) }
}
#[allow(clippy::missing_safety_doc)]
pub unsafe fn forget_mut<'a, T>(x: &mut T) -> &'a mut T {
unsafe { std::mem::transmute::<&mut T, &mut T>(x) }
}
#[allow(clippy::mut_from_ref, clippy::missing_safety_doc)]
pub unsafe fn to_mut<T>(x: &T) -> &mut T {
#[allow(mutable_transmutes)]
unsafe {
std::mem::transmute::<&T, &mut T>(x)
}
}

View File

@@ -56,11 +56,6 @@ impl<State, W: ?Sized> WidgetHandle<State, W> {
} }
} }
pub fn as_any(&self) -> &WidgetHandle<State, dyn Widget<State>> {
// SAFETY: self is repr(C) and generic only used for phantom data
unsafe { std::mem::transmute(self) }
}
pub fn id(&self) -> WidgetId { pub fn id(&self) -> WidgetId {
self.id self.id
} }

View File

@@ -1,6 +1,6 @@
use crate::{ use crate::{
IdLike, Widget, WidgetData, WidgetId, IdLike, Widget, WidgetData, WidgetId,
util::{DynBorrower, HashSet, SlotVec}, util::{DynBorrower, HashSet, SlotVec, forget_mut, to_mut},
}; };
pub struct Widgets<State> { pub struct Widgets<State> {
@@ -36,12 +36,7 @@ impl<State: 'static> Widgets<State> {
pub(crate) fn get_dyn_dynamic<'a>(&self, id: WidgetId) -> WidgetWrapper<'a, State> { pub(crate) fn get_dyn_dynamic<'a>(&self, id: WidgetId) -> WidgetWrapper<'a, State> {
// SAFETY: must guarantee no other mutable references to this widget exist // SAFETY: must guarantee no other mutable references to this widget exist
// done through the borrow variable // done through the borrow variable
#[allow(mutable_transmutes)] let data = unsafe { forget_mut(to_mut(self.vec.get(id).unwrap())) };
let data = unsafe {
std::mem::transmute::<&WidgetData<State>, &mut WidgetData<State>>(
self.vec.get(id).unwrap(),
)
};
if data.borrowed { if data.borrowed {
panic!("tried to mutably borrow the same widget twice"); panic!("tried to mutably borrow the same widget twice");
} }

View File

@@ -1,5 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
use arboard::Clipboard; use arboard::Clipboard;
use iris_core::util::forget_mut;
use std::{marker::Sized, sync::Arc, time::Instant}; use std::{marker::Sized, sync::Arc, time::Instant};
use winit::{ use winit::{
event::{Ime, WindowEvent}, event::{Ime, WindowEvent},
@@ -52,10 +53,7 @@ pub trait HasUiState: Sized + 'static + HasUi {
fn ui_state(&mut self) -> &mut UiState<Self>; fn ui_state(&mut self) -> &mut UiState<Self>;
fn ui_with_ui_state(&mut self) -> (&mut Ui<Self>, &mut UiState<Self>) { fn ui_with_ui_state(&mut self) -> (&mut Ui<Self>, &mut UiState<Self>) {
// as long as you're not doing anything actually unhinged this should always work safely // as long as you're not doing anything actually unhinged this should always work safely
( (unsafe { forget_mut(self.ui()) }, self.ui_state())
unsafe { std::mem::transmute::<&mut Ui<Self>, &mut Ui<Self>>(self.ui()) },
self.ui_state(),
)
} }
} }