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