diff --git a/core/src/primitive/layer.rs b/core/src/primitive/layer.rs index b841602..54f6a96 100644 --- a/core/src/primitive/layer.rs +++ b/core/src/primitive/layer.rs @@ -1,6 +1,9 @@ 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; @@ -176,8 +179,7 @@ impl<'a, T> Iterator for LayerIteratorMut<'a, T> { fn next(&mut self) -> Option { let i = self.inner.next()?; // SAFETY: requires index iterator to work properly - #[allow(mutable_transmutes)] - let layer = unsafe { std::mem::transmute::<&T, &mut T>(&self.inner.vec[i].data) }; + let layer = unsafe { to_mut(&self.inner.vec[i].data) }; Some((i, layer)) } } @@ -186,8 +188,7 @@ impl<'a, T> DoubleEndedIterator for LayerIteratorMut<'a, T> { fn next_back(&mut self) -> Option { let i = self.inner.next_back()?; // SAFETY: requires index iterator to work properly - #[allow(mutable_transmutes)] - let layer = unsafe { std::mem::transmute::<&T, &mut T>(&self.inner.vec[i].data) }; + let layer = unsafe { to_mut(&self.inner.vec[i].data) }; Some((i, layer)) } } diff --git a/core/src/ui/draw_state.rs b/core/src/ui/draw_state.rs index 91c8cd2..cc25647 100644 --- a/core/src/ui/draw_state.rs +++ b/core/src/ui/draw_state.rs @@ -1,6 +1,7 @@ use crate::{ - ActiveData, Axis, Painter, SizeCtx, Ui, UiRegion, UiVec2, WidgetId, render::MaskIdx, - util::HashSet, + ActiveData, Axis, Painter, SizeCtx, Ui, UiRegion, UiVec2, WidgetId, + render::MaskIdx, + util::{HashSet, forget_ref}, }; use std::ops::{Deref, DerefMut}; @@ -30,9 +31,7 @@ impl<'a, State: 'static> DrawState<'a, State> { /// will just return if so pub fn redraw(&mut self, id: WidgetId) { self.widgets.needs_redraw.remove(&id); - if self.draw_started.contains(&id) { - return; - } + self.draw_started.remove(&id); // check if parent depends on the desired size of this, if so then redraw it first for axis in [Axis::X, Axis::Y] { 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); } active.region = active.region.outside(&from).within(&to); - // children will not be changed, so this technically should not be needed - // probably need unsafe - let children = active.children.clone(); + // SAFETY: children cannot be recursive + let children = unsafe { forget_ref(&active.children) }; for child in children { - self.mov(child, from, to); + self.mov(*child, from, to); } } diff --git a/core/src/util/mod.rs b/core/src/util/mod.rs index ec45deb..69c3331 100644 --- a/core/src/util/mod.rs +++ b/core/src/util/mod.rs @@ -1,4 +1,3 @@ -mod typemap; mod arena; mod borrow; mod change; @@ -6,9 +5,10 @@ mod id; mod math; mod refcount; mod slot; +mod trust; +mod typemap; mod vec2; -pub use typemap::*; pub use arena::*; pub use borrow::*; pub use change::*; @@ -16,6 +16,8 @@ pub use id::*; pub use math::*; pub use refcount::*; pub use slot::*; +pub use trust::*; +pub use typemap::*; pub use vec2::*; pub type HashMap = fxhash::FxHashMap; diff --git a/core/src/util/trust.rs b/core/src/util/trust.rs new file mode 100644 index 0000000..b9d1a6b --- /dev/null +++ b/core/src/util/trust.rs @@ -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(x: &T) -> &mut T { + #[allow(mutable_transmutes)] + unsafe { + std::mem::transmute::<&T, &mut T>(x) + } +} diff --git a/core/src/widget/handle.rs b/core/src/widget/handle.rs index 49f7c3a..521c818 100644 --- a/core/src/widget/handle.rs +++ b/core/src/widget/handle.rs @@ -56,11 +56,6 @@ impl WidgetHandle { } } - pub fn as_any(&self) -> &WidgetHandle> { - // SAFETY: self is repr(C) and generic only used for phantom data - unsafe { std::mem::transmute(self) } - } - pub fn id(&self) -> WidgetId { self.id } diff --git a/core/src/widget/widgets.rs b/core/src/widget/widgets.rs index 6fb44bb..df84afe 100644 --- a/core/src/widget/widgets.rs +++ b/core/src/widget/widgets.rs @@ -1,6 +1,6 @@ use crate::{ IdLike, Widget, WidgetData, WidgetId, - util::{DynBorrower, HashSet, SlotVec}, + util::{DynBorrower, HashSet, SlotVec, forget_mut, to_mut}, }; pub struct Widgets { @@ -36,12 +36,7 @@ impl Widgets { pub(crate) fn get_dyn_dynamic<'a>(&self, id: WidgetId) -> WidgetWrapper<'a, State> { // SAFETY: must guarantee no other mutable references to this widget exist // done through the borrow variable - #[allow(mutable_transmutes)] - let data = unsafe { - std::mem::transmute::<&WidgetData, &mut WidgetData>( - self.vec.get(id).unwrap(), - ) - }; + let data = unsafe { forget_mut(to_mut(self.vec.get(id).unwrap())) }; if data.borrowed { panic!("tried to mutably borrow the same widget twice"); } diff --git a/src/default/mod.rs b/src/default/mod.rs index 63ac348..ad1e3a8 100644 --- a/src/default/mod.rs +++ b/src/default/mod.rs @@ -1,5 +1,6 @@ use crate::prelude::*; use arboard::Clipboard; +use iris_core::util::forget_mut; use std::{marker::Sized, sync::Arc, time::Instant}; use winit::{ event::{Ime, WindowEvent}, @@ -52,10 +53,7 @@ pub trait HasUiState: Sized + 'static + HasUi { fn ui_state(&mut self) -> &mut UiState; fn ui_with_ui_state(&mut self) -> (&mut Ui, &mut UiState) { // as long as you're not doing anything actually unhinged this should always work safely - ( - unsafe { std::mem::transmute::<&mut Ui, &mut Ui>(self.ui()) }, - self.ui_state(), - ) + (unsafe { forget_mut(self.ui()) }, self.ui_state()) } }