//! Reflection-based dynamic functions.1//!2//! This module provides a way to pass around and call functions dynamically3//! using the [`DynamicFunction`] and [`DynamicFunctionMut`] types.4//!5//! Many simple functions and closures can be automatically converted to these types6//! using the [`IntoFunction`] and [`IntoFunctionMut`] traits, respectively.7//!8//! Once this dynamic representation is created, it can be called with a set of arguments provided9//! via an [`ArgList`].10//!11//! This returns a [`FunctionResult`] containing the [`Return`] value,12//! which can be used to extract a [`PartialReflect`] trait object.13//!14//! # Example15//!16//! ```17//! # use bevy_reflect::PartialReflect;18//! # use bevy_reflect::func::args::ArgList;19//! # use bevy_reflect::func::{DynamicFunction, FunctionResult, IntoFunction, Return};20//! fn add(a: i32, b: i32) -> i32 {21//! a + b22//! }23//!24//! let mut func: DynamicFunction = add.into_function();25//! let args: ArgList = ArgList::default()26//! // Pushing a known type with owned ownership27//! .with_owned(25_i32)28//! // Pushing a reflected type with owned ownership29//! .with_boxed(Box::new(75_i32) as Box<dyn PartialReflect>);30//! let result: FunctionResult = func.call(args);31//! let value: Return = result.unwrap();32//! assert_eq!(value.unwrap_owned().try_downcast_ref::<i32>(), Some(&100));33//! ```34//!35//! # Types of Functions36//!37//! For simplicity, this module uses the umbrella term "function" to refer to any Rust callable:38//! code that can be invoked with a set of arguments to perform some action.39//!40//! In Rust, there are two main categories of callables: functions and closures.41//!42//! A "function" is a callable that does not capture its environment.43//! These are typically defined with the `fn` keyword, which are referred to as _named_ functions.44//! But there are also _anonymous_ functions, which are unnamed and defined with anonymous function syntax.45//!46//! ```rust47//! // This is a named function:48//! fn add(a: i32, b: i32) -> i32 {49//! a + b50//! }51//!52//! // This is an anonymous function:53//! let add = |a: i32, b: i32| a + b;54//! ```55//!56//! Closures, on the other hand, are special functions that do capture their environment.57//! These are always defined with anonymous function syntax.58//!59//! ```60//! // A closure that captures an immutable reference to a variable61//! let c = 123;62//! let add = |a: i32, b: i32| a + b + c;63//!64//! // A closure that captures a mutable reference to a variable65//! let mut total = 0;66//! let add = |a: i32, b: i32| total += a + b;67//!68//! // A closure that takes ownership of its captured variables by moving them69//! let c = 123;70//! let add = move |a: i32, b: i32| a + b + c;71//! ```72//!73//! # Valid Signatures74//!75//! Many of the traits in this module have default blanket implementations over a specific set of function signatures.76//!77//! These signatures are:78//! - `(...) -> R`79//! - `for<'a> (&'a arg, ...) -> &'a R`80//! - `for<'a> (&'a mut arg, ...) -> &'a R`81//! - `for<'a> (&'a mut arg, ...) -> &'a mut R`82//!83//! Where `...` represents 0 to 15 arguments (inclusive) of the form `T`, `&T`, or `&mut T`.84//! The lifetime of any reference to the return type `R`, must be tied to a "receiver" argument85//! (i.e. the first argument in the signature, normally `self`).86//!87//! Each trait will also have its own requirements for what traits are required for both arguments and return types,88//! but a good rule-of-thumb is that all types should derive [`Reflect`].89//!90//! The reason for such a small subset of valid signatures is due to limitations in Rust—91//! namely the [lack of variadic generics] and certain [coherence issues].92//!93//! For other functions that don't conform to one of the above signatures,94//! [`DynamicFunction`] and [`DynamicFunctionMut`] can instead be created manually.95//!96//! # Generic Functions97//!98//! In Rust, generic functions are [monomorphized] by the compiler,99//! which means that a separate copy of the function is generated for each concrete set of type parameters.100//!101//! When converting a generic function to a [`DynamicFunction`] or [`DynamicFunctionMut`],102//! the function must be manually monomorphized with concrete types.103//! In other words, you cannot write `add<T>.into_function()`.104//! Instead, you will need to write `add::<i32>.into_function()`.105//!106//! This means that reflected functions cannot be generic themselves.107//! To get around this limitation, you can consider [overloading] your function with multiple concrete types.108//!109//! # Overloading Functions110//!111//! Both [`DynamicFunction`] and [`DynamicFunctionMut`] support [function overloading].112//!113//! Function overloading allows one function to handle multiple types of arguments.114//! This is useful for simulating generic functions by having an overload for each known concrete type.115//! Additionally, it can also simulate [variadic functions]: functions that can be called with a variable number of arguments.116//!117//! Internally, this works by storing multiple functions in a map,118//! where each function is associated with a specific argument signature.119//!120//! To learn more, see the docs on [`DynamicFunction::with_overload`].121//!122//! # Function Registration123//!124//! This module also provides a [`FunctionRegistry`] that can be used to register functions and closures125//! by name so that they may be retrieved and called dynamically.126//!127//! ```128//! # use bevy_reflect::func::{ArgList, FunctionRegistry};129//! fn add(a: i32, b: i32) -> i32 {130//! a + b131//! }132//!133//! let mut registry = FunctionRegistry::default();134//!135//! // You can register functions and methods by their `core::any::type_name`:136//! registry.register(add).unwrap();137//!138//! // Or you can register them by a custom name:139//! registry.register_with_name("mul", |a: i32, b: i32| a * b).unwrap();140//!141//! // You can then retrieve and call these functions by name:142//! let reflect_add = registry.get(core::any::type_name_of_val(&add)).unwrap();143//! let value = reflect_add.call(ArgList::default().with_owned(10_i32).with_owned(5_i32)).unwrap();144//! assert_eq!(value.unwrap_owned().try_downcast_ref::<i32>(), Some(&15));145//!146//! let reflect_mul = registry.get("mul").unwrap();147//! let value = reflect_mul.call(ArgList::default().with_owned(10_i32).with_owned(5_i32)).unwrap();148//! assert_eq!(value.unwrap_owned().try_downcast_ref::<i32>(), Some(&50));149//! ```150//!151//! [`PartialReflect`]: crate::PartialReflect152//! [`Reflect`]: crate::Reflect153//! [lack of variadic generics]: https://poignardazur.github.io/2024/05/25/report-on-rustnl-variadics/154//! [coherence issues]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#coherence-leak-check155//! [monomorphized]: https://en.wikipedia.org/wiki/Monomorphization156//! [overloading]: #overloading-functions157//! [function overloading]: https://en.wikipedia.org/wiki/Function_overloading158//! [variadic functions]: https://en.wikipedia.org/wiki/Variadic_function159160pub use args::{ArgError, ArgList, ArgValue};161pub use dynamic_function::*;162pub use dynamic_function_mut::*;163pub use error::*;164pub use function::*;165pub use info::*;166pub use into_function::*;167pub use into_function_mut::*;168pub use reflect_fn::*;169pub use reflect_fn_mut::*;170pub use registry::*;171pub use return_type::*;172173pub mod args;174mod dynamic_function;175mod dynamic_function_internal;176mod dynamic_function_mut;177mod error;178mod function;179mod info;180mod into_function;181mod into_function_mut;182pub(crate) mod macros;183mod reflect_fn;184mod reflect_fn_mut;185mod registry;186mod return_type;187pub mod signature;188189#[cfg(test)]190mod tests {191use alloc::borrow::Cow;192193use super::*;194use crate::func::args::ArgCount;195use crate::{196func::args::{ArgError, ArgList, Ownership},197TypePath,198};199200#[test]201fn should_error_on_missing_args() {202fn foo(_: i32) {}203204let func = foo.into_function();205let args = ArgList::new();206let result = func.call(args);207assert_eq!(208result.unwrap_err(),209FunctionError::ArgCountMismatch {210expected: ArgCount::new(1).unwrap(),211received: 0212}213);214}215216#[test]217fn should_error_on_too_many_args() {218fn foo() {}219220let func = foo.into_function();221let args = ArgList::new().with_owned(123_i32);222let result = func.call(args);223assert_eq!(224result.unwrap_err(),225FunctionError::ArgCountMismatch {226expected: ArgCount::new(0).unwrap(),227received: 1228}229);230}231232#[test]233fn should_error_on_invalid_arg_type() {234fn foo(_: i32) {}235236let func = foo.into_function();237let args = ArgList::new().with_owned(123_u32);238let result = func.call(args);239assert_eq!(240result.unwrap_err(),241FunctionError::ArgError(ArgError::UnexpectedType {242index: 0,243expected: Cow::Borrowed(i32::type_path()),244received: Cow::Borrowed(u32::type_path())245})246);247}248249#[test]250fn should_error_on_invalid_arg_ownership() {251fn foo(_: &i32) {}252253let func = foo.into_function();254let args = ArgList::new().with_owned(123_i32);255let result = func.call(args);256assert_eq!(257result.unwrap_err(),258FunctionError::ArgError(ArgError::InvalidOwnership {259index: 0,260expected: Ownership::Ref,261received: Ownership::Owned262})263);264}265}266267268