Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_reflect/src/func/reflect_fn_mut.rs
6599 views
1
use variadics_please::all_tuples;
2
3
use crate::{
4
func::{
5
args::{ArgCount, FromArg},
6
macros::count_tokens,
7
ArgList, FunctionError, FunctionResult, IntoReturn,
8
},
9
Reflect, TypePath,
10
};
11
12
/// A reflection-based version of the [`FnMut`] trait.
13
///
14
/// This allows functions to be called dynamically through [reflection].
15
///
16
/// This is a supertrait of [`ReflectFn`], and is used for functions that may mutate their environment,
17
/// such as closures that capture mutable references.
18
///
19
/// # Blanket Implementation
20
///
21
/// This trait has a blanket implementation that covers everything that [`ReflectFn`] does:
22
/// - Functions and methods defined with the `fn` keyword
23
/// - Anonymous functions
24
/// - Function pointers
25
/// - Closures that capture immutable references to their environment
26
/// - Closures that take ownership of captured variables
27
///
28
/// But also allows for:
29
/// - Closures that capture mutable references to their environment
30
///
31
/// For each of the above cases, the function signature may only have up to 15 arguments,
32
/// not including an optional receiver argument (often `&self` or `&mut self`).
33
/// This optional receiver argument may be either a mutable or immutable reference to a type.
34
/// If the return type is also a reference, its lifetime will be bound to the lifetime of this receiver.
35
///
36
/// See the [module-level documentation] for more information on valid signatures.
37
///
38
/// Arguments are expected to implement [`FromArg`], and the return type is expected to implement [`IntoReturn`].
39
/// Both of these traits are automatically implemented when using the `Reflect` [derive macro].
40
///
41
/// # Example
42
///
43
/// ```
44
/// # use bevy_reflect::func::{ArgList, FunctionInfo, ReflectFnMut};
45
/// #
46
/// let mut list: Vec<i32> = vec![1, 3];
47
///
48
/// // `insert` is a closure that captures a mutable reference to `list`
49
/// let mut insert = |index: usize, value: i32| {
50
/// list.insert(index, value);
51
/// };
52
///
53
/// let args = ArgList::new().with_owned(1_usize).with_owned(2_i32);
54
///
55
/// insert.reflect_call_mut(args).unwrap();
56
/// assert_eq!(list, vec![1, 2, 3]);
57
/// ```
58
///
59
/// # Trait Parameters
60
///
61
/// This trait has a `Marker` type parameter that is used to get around issues with
62
/// [unconstrained type parameters] when defining impls with generic arguments or return types.
63
/// This `Marker` can be any type, provided it doesn't conflict with other implementations.
64
///
65
/// Additionally, it has a lifetime parameter, `'env`, that is used to bound the lifetime of the function.
66
/// For named functions and some closures, this will end up just being `'static`,
67
/// however, closures that borrow from their environment will have a lifetime bound to that environment.
68
///
69
/// [reflection]: crate
70
/// [`ReflectFn`]: crate::func::ReflectFn
71
/// [module-level documentation]: crate::func
72
/// [derive macro]: derive@crate::Reflect
73
/// [unconstrained type parameters]: https://doc.rust-lang.org/error_codes/E0207.html
74
pub trait ReflectFnMut<'env, Marker> {
75
/// Call the function with the given arguments and return the result.
76
fn reflect_call_mut<'a>(&mut self, args: ArgList<'a>) -> FunctionResult<'a>;
77
}
78
79
/// Helper macro for implementing [`ReflectFnMut`] on Rust functions.
80
///
81
/// This currently implements it for the following signatures (where `argX` may be any of `T`, `&T`, or `&mut T`):
82
/// - `FnMut(arg0, arg1, ..., argN) -> R`
83
/// - `FnMut(&Receiver, arg0, arg1, ..., argN) -> &R`
84
/// - `FnMut(&mut Receiver, arg0, arg1, ..., argN) -> &mut R`
85
/// - `FnMut(&mut Receiver, arg0, arg1, ..., argN) -> &R`
86
macro_rules! impl_reflect_fn_mut {
87
($(($Arg:ident, $arg:ident)),*) => {
88
// === (...) -> ReturnType === //
89
impl<'env, $($Arg,)* ReturnType, Function> ReflectFnMut<'env, fn($($Arg),*) -> [ReturnType]> for Function
90
where
91
$($Arg: FromArg,)*
92
// This clause allows us to convert `ReturnType` into `Return`
93
ReturnType: IntoReturn + Reflect,
94
Function: FnMut($($Arg),*) -> ReturnType + 'env,
95
// This clause essentially asserts that `Arg::This` is the same type as `Arg`
96
Function: for<'a> FnMut($($Arg::This<'a>),*) -> ReturnType + 'env,
97
{
98
#[expect(
99
clippy::allow_attributes,
100
reason = "This lint is part of a macro, which may not always trigger the `unused_mut` lint."
101
)]
102
#[allow(
103
unused_mut,
104
reason = "Some invocations of this macro may trigger the `unused_mut` lint, where others won't."
105
)]
106
fn reflect_call_mut<'a>(&mut self, mut args: ArgList<'a>) -> FunctionResult<'a> {
107
const COUNT: usize = count_tokens!($($Arg)*);
108
109
if args.len() != COUNT {
110
return Err(FunctionError::ArgCountMismatch {
111
expected: ArgCount::new(COUNT).unwrap(),
112
received: args.len(),
113
});
114
}
115
116
// Extract all arguments (in order)
117
$(let $arg = args.take::<$Arg>()?;)*
118
119
Ok((self)($($arg,)*).into_return())
120
}
121
}
122
123
// === (&self, ...) -> &ReturnType === //
124
impl<'env, Receiver, $($Arg,)* ReturnType, Function> ReflectFnMut<'env, fn(&Receiver, $($Arg),*) -> &ReturnType> for Function
125
where
126
Receiver: Reflect + TypePath,
127
$($Arg: FromArg,)*
128
ReturnType: Reflect,
129
// This clause allows us to convert `&ReturnType` into `Return`
130
for<'a> &'a ReturnType: IntoReturn,
131
Function: for<'a> FnMut(&'a Receiver, $($Arg),*) -> &'a ReturnType + 'env,
132
// This clause essentially asserts that `Arg::This` is the same type as `Arg`
133
Function: for<'a> FnMut(&'a Receiver, $($Arg::This<'a>),*) -> &'a ReturnType + 'env,
134
{
135
fn reflect_call_mut<'a>(&mut self, mut args: ArgList<'a>) -> FunctionResult<'a> {
136
const COUNT: usize = count_tokens!(Receiver $($Arg)*);
137
138
if args.len() != COUNT {
139
return Err(FunctionError::ArgCountMismatch {
140
expected: ArgCount::new(COUNT).unwrap(),
141
received: args.len(),
142
});
143
}
144
145
// Extract all arguments (in order)
146
let receiver = args.take_ref::<Receiver>()?;
147
$(let $arg = args.take::<$Arg>()?;)*
148
149
Ok((self)(receiver, $($arg,)*).into_return())
150
}
151
}
152
153
// === (&mut self, ...) -> &mut ReturnType === //
154
impl<'env, Receiver, $($Arg,)* ReturnType, Function> ReflectFnMut<'env, fn(&mut Receiver, $($Arg),*) -> &mut ReturnType> for Function
155
where
156
Receiver: Reflect + TypePath,
157
$($Arg: FromArg,)*
158
ReturnType: Reflect,
159
// This clause allows us to convert `&mut ReturnType` into `Return`
160
for<'a> &'a mut ReturnType: IntoReturn,
161
Function: for<'a> FnMut(&'a mut Receiver, $($Arg),*) -> &'a mut ReturnType + 'env,
162
// This clause essentially asserts that `Arg::This` is the same type as `Arg`
163
Function: for<'a> FnMut(&'a mut Receiver, $($Arg::This<'a>),*) -> &'a mut ReturnType + 'env,
164
{
165
fn reflect_call_mut<'a>(&mut self, mut args: ArgList<'a>) -> FunctionResult<'a> {
166
const COUNT: usize = count_tokens!(Receiver $($Arg)*);
167
168
if args.len() != COUNT {
169
return Err(FunctionError::ArgCountMismatch {
170
expected: ArgCount::new(COUNT).unwrap(),
171
received: args.len(),
172
});
173
}
174
175
// Extract all arguments (in order)
176
let receiver = args.take_mut::<Receiver>()?;
177
$(let $arg = args.take::<$Arg>()?;)*
178
179
Ok((self)(receiver, $($arg,)*).into_return())
180
}
181
}
182
183
// === (&mut self, ...) -> &ReturnType === //
184
impl<'env, Receiver, $($Arg,)* ReturnType, Function> ReflectFnMut<'env, fn(&mut Receiver, $($Arg),*) -> &ReturnType> for Function
185
where
186
Receiver: Reflect + TypePath,
187
$($Arg: FromArg,)*
188
ReturnType: Reflect,
189
// This clause allows us to convert `&ReturnType` into `Return`
190
for<'a> &'a ReturnType: IntoReturn,
191
Function: for<'a> FnMut(&'a mut Receiver, $($Arg),*) -> &'a ReturnType + 'env,
192
// This clause essentially asserts that `Arg::This` is the same type as `Arg`
193
Function: for<'a> FnMut(&'a mut Receiver, $($Arg::This<'a>),*) -> &'a ReturnType + 'env,
194
{
195
fn reflect_call_mut<'a>(&mut self, mut args: ArgList<'a>) -> FunctionResult<'a> {
196
const COUNT: usize = count_tokens!(Receiver $($Arg)*);
197
198
if args.len() != COUNT {
199
return Err(FunctionError::ArgCountMismatch {
200
expected: ArgCount::new(COUNT).unwrap(),
201
received: args.len(),
202
});
203
}
204
205
// Extract all arguments (in order)
206
let receiver = args.take_mut::<Receiver>()?;
207
$(let $arg = args.take::<$Arg>()?;)*
208
209
Ok((self)(receiver, $($arg,)*).into_return())
210
}
211
}
212
};
213
}
214
215
all_tuples!(impl_reflect_fn_mut, 0, 15, Arg, arg);
216
217