1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00

Remove the as_any fns

This commit is contained in:
lucasmerlin
2026-04-23 16:58:19 +02:00
parent e318a72717
commit 65ce0efa2f
3 changed files with 13 additions and 36 deletions

View File

@@ -220,19 +220,22 @@ impl<'a, State: 'static> Harness<'a, State> {
pub fn plugin<P: Plugin<State>>(&self) -> Option<&P> {
self.plugins
.iter()
.find_map(|p| p.as_any().downcast_ref::<P>())
.find_map(|p| (&**p as &dyn std::any::Any).downcast_ref::<P>())
}
/// Mutably borrow a registered plugin by type.
pub fn plugin_mut<P: Plugin<State>>(&mut self) -> Option<&mut P> {
self.plugins
.iter_mut()
.find_map(|p| p.as_any_mut().downcast_mut::<P>())
.find_map(|p| (&mut **p as &mut dyn std::any::Any).downcast_mut::<P>())
}
/// Remove and return the first plugin of the given type.
pub fn take_plugin<P: Plugin<State>>(&mut self) -> Option<Box<P>> {
let idx = self.plugins.iter().position(|p| p.as_any().is::<P>())?;
let idx = self
.plugins
.iter()
.position(|p| (&**p as &dyn std::any::Any).is::<P>())?;
let boxed = self.plugins.remove(idx);
let raw: *mut dyn Plugin<State> = Box::into_raw(boxed);
// SAFETY: `is::<P>()` confirmed the concrete type is `P`. Fat-to-thin pointer

View File

@@ -22,11 +22,15 @@ use crate::{ExceededMaxStepsError, Harness};
/// fn after_step(&mut self, _harness: &mut Harness<'_, S>) {
/// // ...
/// }
/// fn as_any(&self) -> &dyn std::any::Any { self }
/// fn as_any_mut(&mut self) -> &mut dyn std::any::Any { self }
/// }
/// ```
///
/// # Downcasting
///
/// [`Any`] is a supertrait, so [`Harness::plugin`] / [`Harness::plugin_mut`] /
/// [`Harness::take_plugin`] downcast registered plugins back to their concrete type via
/// trait upcasting. No boilerplate needed on your end.
///
/// # Re-entrancy
///
/// Plugin hooks receive `&mut Harness`. Calling [`Harness::step`] / [`Harness::run`] /
@@ -35,7 +39,7 @@ use crate::{ExceededMaxStepsError, Harness};
/// harness from inside a hook — e.g. an inspector that blocks on user input — use
/// [`Harness::advance_frame`] instead.
#[expect(unused_variables, reason = "default no-op impls")]
pub trait Plugin<State = ()>: Send + 'static {
pub trait Plugin<State = ()>: Send + Any {
/// Called once at the start of every `run()` / `try_run()` / `try_run_realtime()` /
/// `run_ok()` invocation, before the first step.
fn before_run(&mut self, harness: &mut Harness<'_, State>) {}
@@ -85,12 +89,6 @@ pub trait Plugin<State = ()>: Send + 'static {
/// called [`install_panic_hook`]. Without the hook, the variant still flips to
/// `Fail` but both fields are `None`.
fn on_test_result(&mut self, harness: &mut Harness<'_, State>, result: TestResult<'_>) {}
/// Downcast support — implement as `self`.
fn as_any(&self) -> &dyn Any;
/// Downcast support — implement as `self`.
fn as_any_mut(&mut self) -> &mut dyn Any;
}
/// Location of a panic — a `std::panic::Location` stripped of its borrow so it can be

View File

@@ -71,12 +71,6 @@ impl<S> Plugin<S> for CountingPlugin {
TestResult::Fail { .. } => "on_test_result:fail",
});
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
/// Lifecycle ordering: a simple run+drop cycle fires the expected hooks in order.
@@ -141,12 +135,6 @@ fn advance_frame_skips_hooks() {
h.advance_frame();
}
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
let log: Log = Arc::default();
@@ -188,12 +176,6 @@ fn mid_dispatch_registration_is_deferred() {
h.add_plugin(latecomer);
}
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
let log: Log = Arc::default();
@@ -263,12 +245,6 @@ fn reentrant_step_panics_in_debug() {
// Forbidden: step from inside a hook.
h.step();
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
let mut harness = Harness::builder().with_plugin(Misbehaver).build_ui(|ui| {