Remove the AsAny helper trait

Trait upcasting (rust-lang/rust#65991) is stable since Rust 1.86, which
is already the MSRV, so dyn trait objects coerce to dyn Any directly.
Traits that needed AsAny now list Any as their supertrait, and the
as_any module is renamed to casting as only the impl_dyn_casting macro
remains.
This commit is contained in:
Olivier Goffart
2026-07-28 17:29:27 +00:00
parent c5eee2fb52
commit 874a1e31f1
8 changed files with 21 additions and 58 deletions

View File

@@ -1,36 +1,3 @@
use std::any::Any;
// NOTE: This is `pub`, but isn't actually exposed outside the crate.
// NOTE: Marked as `#[doc(hidden)]` and underscored, because they can be quite difficult to use
// correctly, see discussion in #4160.
// FIXME: Remove and replace with a coercion once rust-lang/rust#65991 is in MSRV (1.86).
#[doc(hidden)]
pub trait AsAny: Any {
#[doc(hidden)]
fn __as_any(&self) -> &dyn Any;
#[doc(hidden)]
fn __as_any_mut(&mut self) -> &mut dyn Any;
#[doc(hidden)]
fn __into_any(self: Box<Self>) -> Box<dyn Any>;
}
impl<T: Any> AsAny for T {
#[inline(always)]
fn __as_any(&self) -> &dyn Any {
self
}
#[inline(always)]
fn __as_any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline(always)]
fn __into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
}
#[macro_export]
macro_rules! impl_dyn_casting {
($trait:ident) => {
@@ -39,7 +6,7 @@ macro_rules! impl_dyn_casting {
///
/// Returns `None` if the object was not from that backend.
pub fn cast_ref<T: $trait>(&self) -> Option<&T> {
let this: &dyn std::any::Any = self.__as_any();
let this: &dyn std::any::Any = self;
this.downcast_ref::<T>()
}
@@ -47,7 +14,7 @@ macro_rules! impl_dyn_casting {
///
/// Returns `None` if the object was not from that backend.
pub fn cast_mut<T: $trait>(&mut self) -> Option<&mut T> {
let this: &mut dyn std::any::Any = self.__as_any_mut();
let this: &mut dyn std::any::Any = self;
this.downcast_mut::<T>()
}
@@ -56,7 +23,7 @@ macro_rules! impl_dyn_casting {
/// Returns `Err` with `self` if the object was not from that backend.
pub fn cast<T: $trait>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
if self.cast_ref::<T>().is_some() {
let this: Box<dyn std::any::Any> = self.__into_any();
let this: Box<dyn std::any::Any> = self;
// Unwrap is okay, we just checked the type of `self` is `T`.
Ok(this.downcast::<T>().unwrap())
} else {
@@ -71,10 +38,10 @@ pub use impl_dyn_casting;
#[cfg(test)]
mod tests {
use super::AsAny;
use std::any::Any;
struct Foo;
trait FooTrait: AsAny {}
trait FooTrait: Any {}
impl FooTrait for Foo {}
impl_dyn_casting!(FooTrait);

View File

@@ -1,4 +1,5 @@
use core::fmt;
use std::any::Any;
use std::error::Error;
use std::hash::Hash;
use std::ops::Deref;
@@ -8,8 +9,6 @@ use std::time::Duration;
#[doc(inline)]
pub use cursor_icon::CursorIcon;
use crate::as_any::AsAny;
/// The maximum width and height for a cursor when using [`CustomCursorSource::from_rgba`].
pub const MAX_CURSOR_SIZE: u16 = 2048;
@@ -79,7 +78,7 @@ impl From<CustomCursor> for Cursor {
#[derive(Clone, Debug)]
pub struct CustomCursor(pub Arc<dyn CustomCursorProvider>);
pub trait CustomCursorProvider: AsAny + fmt::Debug + Send + Sync {
pub trait CustomCursorProvider: Any + fmt::Debug + Send + Sync {
/// Whether a cursor was backed by animation.
fn is_animated(&self) -> bool;
}

View File

@@ -99,12 +99,11 @@
#![warn(missing_docs)]
use std::any::Any;
use std::ops::ControlFlow;
use std::path::{Path, PathBuf};
use std::{fmt, io};
use crate::as_any::AsAny;
/// Unique identifier for a data transfer.
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DataTransferId(i64);
@@ -194,7 +193,7 @@ impl TypeHint {
///
/// [`hint`](TransferType::hint) can be called to get the type in
/// a cross-platform format (see [`TypeHint`])
pub trait TransferType: AsAny + fmt::Debug {
pub trait TransferType: Any + fmt::Debug {
/// Get the cross-platform representation of this type.
///
/// If this returns `None`, then this is a platform-dependent type that has no cross-platform
@@ -251,7 +250,7 @@ fn default_try_as_file_paths<T: TypedData + ?Sized>(_: &T) -> io::Result<Vec<Pat
/// error with [`io::ErrorKind::Deadlock`]. For now, the only way to access the data is via blocking
/// on the event loop, so simply retrying the next time an event is received that references the
/// data transfer should be enough to ensure that the data is accessible.
pub trait TypedData: AsAny + fmt::Debug + Send + Sync {
pub trait TypedData: Any + fmt::Debug + Send + Sync {
/// The type of this `TypedData`.
fn type_(&self) -> &dyn TransferType;
@@ -329,7 +328,7 @@ impl_dyn_casting!(TypedData);
/// Metadata about a data transfer. This does not allow actually receiving data, as that is an
/// asynchronous operation. To fetch the data from the source application, see
/// [`ActiveEventLoop::fetch_data_transfer`](crate::event_loop::ActiveEventLoop::fetch_data_transfer).
pub trait DataTransfer: AsAny + fmt::Debug {
pub trait DataTransfer: Any + fmt::Debug {
/// Iterate over each type advertized by this `DataTransfer`. This is just a minor optimization,
/// in most cases you should probably use [`has_type`](DataTransfer::has_type) or
/// [`available_types`](DataTransfer::available_types).

View File

@@ -3,6 +3,7 @@ pub mod pump_events;
pub mod register;
pub mod run_on_demand;
use std::any::Any;
use std::fmt::{self, Debug};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
@@ -12,7 +13,6 @@ use rwh_06::{DisplayHandle, HandleError, HasDisplayHandle};
use crate::Instant;
use crate::application::ApplicationHandler;
use crate::as_any::AsAny;
use crate::cursor::{CustomCursor, CustomCursorSource};
use crate::data_transfer::{DataTransfer, DataTransferId, DataTransferSend, TransferType};
use crate::error::{EventLoopError, NotSupportedError, RequestError};
@@ -109,7 +109,7 @@ pub trait EventLoopProvider: fmt::Debug {
) -> Result<CustomCursor, RequestError>;
}
pub trait ActiveEventLoop: AsAny + fmt::Debug {
pub trait ActiveEventLoop: Any + fmt::Debug {
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
/// to the main event loop, possibly from another thread.
fn create_proxy(&self) -> EventLoopProxy;

View File

@@ -1,10 +1,9 @@
use std::any::Any;
use std::error::Error;
use std::ops::Deref;
use std::sync::Arc;
use std::{fmt, io, mem};
use crate::as_any::AsAny;
pub(crate) const PIXEL_SIZE: usize = mem::size_of::<u32>();
/// An icon used for the window titlebar, taskbar, etc.
@@ -12,7 +11,7 @@ pub(crate) const PIXEL_SIZE: usize = mem::size_of::<u32>();
pub struct Icon(pub Arc<dyn IconProvider>);
// TODO remove that once split.
pub trait IconProvider: AsAny + fmt::Debug + Send + Sync {}
pub trait IconProvider: Any + fmt::Debug + Send + Sync {}
impl Deref for Icon {
type Target = dyn IconProvider;

View File

@@ -14,7 +14,7 @@
#![warn(clippy::exhaustive_enums)]
#[macro_use]
pub mod as_any;
pub mod casting;
pub mod cursor;
#[macro_use]
pub mod error;

View File

@@ -5,6 +5,7 @@
//! methods, which return an iterator of [`MonitorHandle`]:
//! - [`ActiveEventLoop::available_monitors`][crate::event_loop::ActiveEventLoop::available_monitors].
//! - [`Window::available_monitors`][crate::window::Window::available_monitors].
use std::any::Any;
use std::borrow::Cow;
use std::fmt;
use std::num::{NonZeroU16, NonZeroU32};
@@ -13,8 +14,6 @@ use std::sync::Arc;
use dpi::{PhysicalPosition, PhysicalSize};
use crate::as_any::AsAny;
/// Handle to a monitor.
///
/// Allows you to retrieve basic information and metadata about a monitor.
@@ -54,7 +53,7 @@ impl PartialEq for MonitorHandle {
impl Eq for MonitorHandle {}
/// Provider of the [`MonitorHandle`].
pub trait MonitorHandleProvider: AsAny + fmt::Debug + Send + Sync {
pub trait MonitorHandleProvider: Any + fmt::Debug + Send + Sync {
/// Identifier for this monitor.
///
/// The representation of this modifier is not guaranteed and should be used only to compare

View File

@@ -1,4 +1,5 @@
//! The [`Window`] trait and associated types.
use std::any::Any;
use std::fmt;
use bitflags::bitflags;
@@ -9,7 +10,6 @@ use dpi::{
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::as_any::AsAny;
use crate::cursor::Cursor;
use crate::error::RequestError;
use crate::icon::Icon;
@@ -513,7 +513,7 @@ pub(crate) struct SendSyncRawWindowHandle(pub(crate) rwh_06::RawWindowHandle);
unsafe impl Send for SendSyncRawWindowHandle {}
unsafe impl Sync for SendSyncRawWindowHandle {}
pub trait PlatformWindowAttributes: AsAny + std::fmt::Debug + Send + Sync {
pub trait PlatformWindowAttributes: Any + std::fmt::Debug + Send + Sync {
fn box_clone(&self) -> Box<dyn PlatformWindowAttributes>;
}
@@ -537,7 +537,7 @@ impl_dyn_casting!(PlatformWindowAttributes);
///
/// **Web:** The [`Window`], which is represented by a `HTMLElementCanvas`, can
/// not be closed by dropping the [`Window`].
pub trait Window: AsAny + Send + Sync + fmt::Debug {
pub trait Window: Any + Send + Sync + fmt::Debug {
/// Returns the window type of this window
fn window_type(&self) -> WindowType;