This is an automated email from the ASF dual-hosted git repository. github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-21803-fe1dd577f706a42d473518cef5c31ff2ec876bee in repository https://gitbox.apache.org/repos/asf/datafusion.git
commit fdaa32608bf620ea7dd9dfabd4d1fd329fafa3e3 Author: Huaijin <[email protected]> AuthorDate: Wed May 13 22:19:52 2026 +0800 feat: impl Any for MemoryPool (#21803) ## Which issue does this PR close? - Closes #21802 ## Rationale for this change - see #21802 ## What changes are included in this PR? implment Any for MemoryPool ## Are these changes tested? yes, add one test case ## Are there any user-facing changes? --------- Co-authored-by: Dmitrii Blaginin <[email protected]> --- datafusion/execution/src/memory_pool/mod.rs | 27 ++++++++++- docs/source/library-user-guide/upgrading/54.0.0.md | 54 ++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/datafusion/execution/src/memory_pool/mod.rs b/datafusion/execution/src/memory_pool/mod.rs index 829e313d23..2b36ee7f40 100644 --- a/datafusion/execution/src/memory_pool/mod.rs +++ b/datafusion/execution/src/memory_pool/mod.rs @@ -19,6 +19,7 @@ //! help with allocation accounting. use datafusion_common::{Result, internal_datafusion_err}; +use std::any::Any; use std::fmt::Display; use std::hash::{Hash, Hasher}; use std::{cmp::Ordering, sync::Arc, sync::atomic}; @@ -182,7 +183,7 @@ pub use pool::*; /// /// * [`TrackConsumersPool`]: Wraps another [`MemoryPool`] and tracks consumers, /// providing better error messages on the largest memory users. -pub trait MemoryPool: Send + Sync + std::fmt::Debug + Display { +pub trait MemoryPool: Any + Send + Sync + std::fmt::Debug + Display { /// Return pool name fn name(&self) -> &str; @@ -224,6 +225,18 @@ pub trait MemoryPool: Send + Sync + std::fmt::Debug + Display { } } +impl dyn MemoryPool { + /// Returns `true` if this pool is of type `T`. + pub fn is<T: MemoryPool>(&self) -> bool { + (self as &dyn Any).is::<T>() + } + + /// Attempts to downcast this pool to a concrete type `T`. + pub fn downcast_ref<T: MemoryPool>(&self) -> Option<&T> { + (self as &dyn Any).downcast_ref() + } +} + /// Memory limit of `MemoryPool` pub enum MemoryLimit { Infinite, @@ -603,6 +616,18 @@ mod tests { assert_eq!(pool.reserved(), 28); } + #[test] + fn test_downcast() { + let pool: Arc<dyn MemoryPool> = Arc::new(GreedyMemoryPool::new(50)); + + assert!(pool.is::<GreedyMemoryPool>()); + assert!(!pool.is::<UnboundedMemoryPool>()); + + let greedy: &GreedyMemoryPool = pool.downcast_ref().unwrap(); + assert_eq!(greedy.reserved(), 0); + assert!(pool.downcast_ref::<UnboundedMemoryPool>().is_none()); + } + #[test] fn test_try_shrink() { let pool = Arc::new(GreedyMemoryPool::new(100)) as _; diff --git a/docs/source/library-user-guide/upgrading/54.0.0.md b/docs/source/library-user-guide/upgrading/54.0.0.md index 0ba3e4eb3e..46b768e834 100644 --- a/docs/source/library-user-guide/upgrading/54.0.0.md +++ b/docs/source/library-user-guide/upgrading/54.0.0.md @@ -595,3 +595,57 @@ impl Default for MyTreeNode { } } ``` + +### `MemoryPool` now requires `'static` (adds `Any` as a supertrait) + +To enable downcasting of `dyn MemoryPool` to concrete pool types (via +`is::<T>()` / `downcast_ref::<T>()`), the `MemoryPool` trait now has `Any` +as a supertrait: + +```rust,ignore +// Before +pub trait MemoryPool: Send + Sync + std::fmt::Debug + Display { ... } + +// After +pub trait MemoryPool: Any + Send + Sync + std::fmt::Debug + Display { ... } +``` + +Because `Any` is only implemented for `'static` types, this implicitly adds a +`'static` bound to every `MemoryPool` implementor. + +**Who is affected:** + +- Users who implement a custom `MemoryPool` whose type carries a lifetime + parameter or borrows state (e.g. `struct MyPool<'a> { inner: &'a State }`). + Existing implementations that are already `'static` (the common case) need + no changes. + +**Migration guide:** + +Replace borrowed references with owned handles so the pool type becomes +`'static`. The typical fix is to swap `&'a T` for `Arc<T>` (or `Rc<T>`, or an +owned value): + +```rust,ignore +// Before — not 'static, no longer compiles +struct MyPool<'a> { + inner: &'a SomeState, +} + +impl<'a> MemoryPool for MyPool<'a> { ... } + +// After — owned handle makes MyPool: 'static +struct MyPool { + inner: Arc<SomeState>, +} + +impl MemoryPool for MyPool { ... } +``` + +If the borrowed state truly cannot be made `'static`, you can wrap the +borrowed pool in a `'static` adapter that the pool consumer owns — for +example, store the underlying state in an `Arc` owned by the adapter, or +move the borrow behind an interior-mutability primitive such as `Arc<Mutex<_>>` +or `Arc<OnceLock<_>>`. + +See [PR #21803](https://github.com/apache/datafusion/pull/21803) for details. --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
