From 874a1e31f194d11313c1ac133b28037b99db3e19 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 28 Jul 2026 17:29:27 +0000 Subject: [PATCH] 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. --- winit-core/src/{as_any.rs => casting.rs} | 43 +++--------------------- winit-core/src/cursor.rs | 5 ++- winit-core/src/data_transfer.rs | 9 +++-- winit-core/src/event_loop/mod.rs | 4 +-- winit-core/src/icon.rs | 5 ++- winit-core/src/lib.rs | 2 +- winit-core/src/monitor.rs | 5 ++- winit-core/src/window.rs | 6 ++-- 8 files changed, 21 insertions(+), 58 deletions(-) rename winit-core/src/{as_any.rs => casting.rs} (60%) diff --git a/winit-core/src/as_any.rs b/winit-core/src/casting.rs similarity index 60% rename from winit-core/src/as_any.rs rename to winit-core/src/casting.rs index 5274bbe7b..e3bdd7653 100644 --- a/winit-core/src/as_any.rs +++ b/winit-core/src/casting.rs @@ -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) -> Box; -} - -impl 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) -> Box { - 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(&self) -> Option<&T> { - let this: &dyn std::any::Any = self.__as_any(); + let this: &dyn std::any::Any = self; this.downcast_ref::() } @@ -47,7 +14,7 @@ macro_rules! impl_dyn_casting { /// /// Returns `None` if the object was not from that backend. pub fn cast_mut(&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::() } @@ -56,7 +23,7 @@ macro_rules! impl_dyn_casting { /// Returns `Err` with `self` if the object was not from that backend. pub fn cast(self: Box) -> Result, Box> { if self.cast_ref::().is_some() { - let this: Box = self.__into_any(); + let this: Box = self; // Unwrap is okay, we just checked the type of `self` is `T`. Ok(this.downcast::().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); diff --git a/winit-core/src/cursor.rs b/winit-core/src/cursor.rs index c411e0d3e..408c9e86d 100644 --- a/winit-core/src/cursor.rs +++ b/winit-core/src/cursor.rs @@ -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 for Cursor { #[derive(Clone, Debug)] pub struct CustomCursor(pub Arc); -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; } diff --git a/winit-core/src/data_transfer.rs b/winit-core/src/data_transfer.rs index c70be7946..6daf18fea 100644 --- a/winit-core/src/data_transfer.rs +++ b/winit-core/src/data_transfer.rs @@ -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) -> io::Result &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). diff --git a/winit-core/src/event_loop/mod.rs b/winit-core/src/event_loop/mod.rs index 38246a85f..4d07b12ee 100644 --- a/winit-core/src/event_loop/mod.rs +++ b/winit-core/src/event_loop/mod.rs @@ -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; } -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; diff --git a/winit-core/src/icon.rs b/winit-core/src/icon.rs index 1d943fc1d..49f807d0d 100644 --- a/winit-core/src/icon.rs +++ b/winit-core/src/icon.rs @@ -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::(); /// An icon used for the window titlebar, taskbar, etc. @@ -12,7 +11,7 @@ pub(crate) const PIXEL_SIZE: usize = mem::size_of::(); pub struct Icon(pub Arc); // 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; diff --git a/winit-core/src/lib.rs b/winit-core/src/lib.rs index 6ea1e2535..508cd0f0d 100644 --- a/winit-core/src/lib.rs +++ b/winit-core/src/lib.rs @@ -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; diff --git a/winit-core/src/monitor.rs b/winit-core/src/monitor.rs index b100710c7..4c5750b61 100644 --- a/winit-core/src/monitor.rs +++ b/winit-core/src/monitor.rs @@ -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 diff --git a/winit-core/src/window.rs b/winit-core/src/window.rs index 0bda71233..2e0247d87 100644 --- a/winit-core/src/window.rs +++ b/winit-core/src/window.rs @@ -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; } @@ -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;