
# Objective One of the changes in #14704 made `DynamicFunction` effectively the same as `DynamicClosure<'static>`. This change meant that the de facto function type would likely be `DynamicClosure<'static>` instead of the intended `DynamicFunction`, since the former is much more flexible. We _could_ explore ways of making `DynamicFunction` implement `Copy` using some unsafe code, but it likely wouldn't be worth it. And users would likely still reach for the convenience of `DynamicClosure<'static>` over the copy-ability of `DynamicFunction`. The goal of this PR is to fix this confusion between the two types. ## Solution Firstly, the `DynamicFunction` type was removed. Again, it was no different than `DynamicClosure<'static>` so it wasn't a huge deal to remove. Secondly, `DynamicClosure<'env>` and `DynamicClosureMut<'env>` were renamed to `DynamicFunction<'env>` and `DynamicFunctionMut<'env>`, respectively. Yes, we still ultimately kept the naming of `DynamicFunction`, but changed its behavior to that of `DynamicClosure<'env>`. We need a term to refer to both functions and closures, and "function" was the best option. [Originally](https://discord.com/channels/691052431525675048/1002362493634629796/1274091992162242710), I was going to go with "callable" as the replacement term to encompass both functions and closures (e.g. `DynamciCallable<'env>`). However, it was [suggested](https://discord.com/channels/691052431525675048/1002362493634629796/1274653581777047625) by @SkiFire13 that the simpler "function" term could be used instead. While "callable" is perhaps the better umbrella term—being truly ambiguous over functions and closures— "function" is more familiar, used more often, easier to discover, and is subjectively just "better-sounding". ## Testing Most changes are purely swapping type names or updating documentation, but you can verify everything still works by running the following command: ``` cargo test --package bevy_reflect ```
104 lines
3.2 KiB
Rust
104 lines
3.2 KiB
Rust
use alloc::borrow::Cow;
|
|
|
|
use crate::func::args::{GetOwnership, Ownership};
|
|
use crate::TypePath;
|
|
|
|
/// Type information for an [`Arg`] used in a [`DynamicFunction`] or [`DynamicFunctionMut`].
|
|
///
|
|
/// [`Arg`]: crate::func::args::Arg
|
|
/// [`DynamicFunction`]: crate::func::DynamicFunction
|
|
/// [`DynamicFunctionMut`]: crate::func::DynamicFunctionMut
|
|
#[derive(Debug, Clone)]
|
|
pub struct ArgInfo {
|
|
/// The index of the argument within its function.
|
|
index: usize,
|
|
/// The name of the argument (if provided).
|
|
name: Option<Cow<'static, str>>,
|
|
/// The ownership of the argument.
|
|
ownership: Ownership,
|
|
/// The [type path] of the argument.
|
|
///
|
|
/// [type path]: TypePath::type_path
|
|
type_path: &'static str,
|
|
}
|
|
|
|
impl ArgInfo {
|
|
/// Create a new [`ArgInfo`] with the given argument index and type `T`.
|
|
///
|
|
/// To set the name of the argument, use [`Self::with_name`].
|
|
pub fn new<T: TypePath + GetOwnership>(index: usize) -> Self {
|
|
Self {
|
|
index,
|
|
name: None,
|
|
ownership: T::ownership(),
|
|
type_path: T::type_path(),
|
|
}
|
|
}
|
|
|
|
/// Set the name of the argument.
|
|
///
|
|
/// Reflected arguments are not required to have a name and by default are not given one,
|
|
/// so this method must be called manually to set the name.
|
|
pub fn with_name(mut self, name: impl Into<Cow<'static, str>>) -> Self {
|
|
self.name = Some(name.into());
|
|
self
|
|
}
|
|
|
|
/// The index of the argument within its function.
|
|
pub fn index(&self) -> usize {
|
|
self.index
|
|
}
|
|
|
|
/// The name of the argument, if it was given one.
|
|
///
|
|
/// Note that this may return `None` even if the argument has a name.
|
|
/// This is because the name needs to be manually set using [`Self::with_name`]
|
|
/// since the name can't be inferred from the function type alone.
|
|
///
|
|
/// For [`DynamicFunctions`] created using [`IntoFunction`]
|
|
/// and [`DynamicFunctionMuts`] created using [`IntoFunctionMut`],
|
|
/// the name will always be `None`.
|
|
///
|
|
/// [`DynamicFunctions`]: crate::func::DynamicFunction
|
|
/// [`IntoFunction`]: crate::func::IntoFunction
|
|
/// [`DynamicFunctionMuts`]: crate::func::DynamicFunctionMut
|
|
/// [`IntoFunctionMut`]: crate::func::IntoFunctionMut
|
|
pub fn name(&self) -> Option<&str> {
|
|
self.name.as_deref()
|
|
}
|
|
|
|
/// The ownership of the argument.
|
|
pub fn ownership(&self) -> Ownership {
|
|
self.ownership
|
|
}
|
|
|
|
/// The [type path] of the argument.
|
|
///
|
|
/// [type path]: TypePath::type_path
|
|
pub fn type_path(&self) -> &'static str {
|
|
self.type_path
|
|
}
|
|
|
|
/// Get an ID representing the argument.
|
|
///
|
|
/// This will return `ArgId::Name` if the argument has a name,
|
|
/// otherwise `ArgId::Index`.
|
|
pub fn id(&self) -> ArgId {
|
|
self.name
|
|
.clone()
|
|
.map(ArgId::Name)
|
|
.unwrap_or_else(|| ArgId::Index(self.index))
|
|
}
|
|
}
|
|
|
|
/// A representation of an argument.
|
|
///
|
|
/// This is primarily used for error reporting and debugging.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum ArgId {
|
|
/// The index of the argument within its function.
|
|
Index(usize),
|
|
/// The name of the argument.
|
|
Name(Cow<'static, str>),
|
|
}
|