diff --git a/crates/bevy_reflect/src/func/dynamic_function.rs b/crates/bevy_reflect/src/func/dynamic_function.rs index c685cf88a0..f227038ce2 100644 --- a/crates/bevy_reflect/src/func/dynamic_function.rs +++ b/crates/bevy_reflect/src/func/dynamic_function.rs @@ -12,7 +12,6 @@ use crate::{ }; use alloc::{borrow::Cow, boxed::Box, sync::Arc}; use bevy_reflect_derive::impl_type_path; -use bevy_utils::HashMap; use core::fmt::{Debug, Formatter}; #[cfg(not(feature = "std"))] @@ -90,7 +89,7 @@ impl<'env> DynamicFunction<'env> { /// [function overloading]: Self::with_overload pub fn new Fn(ArgList<'a>) -> FunctionResult<'a> + Send + Sync + 'env>( func: F, - info: impl TryInto, + info: impl TryInto, Error: Debug>, ) -> Self { let info = info.try_into().unwrap(); @@ -102,19 +101,14 @@ impl<'env> DynamicFunction<'env> { FunctionInfoType::Overloaded(_) => None, }, function_map: match info { - FunctionInfoType::Standard(info) => FunctionMap { - functions: vec![func], - indices: HashMap::from([(ArgumentSignature::from(&info), 0)]), - info: FunctionInfoType::Standard(info), - }, - FunctionInfoType::Overloaded(infos) => FunctionMap { - functions: vec![func], - indices: infos + FunctionInfoType::Standard(info) => FunctionMap::Single(func, info.into_owned()), + FunctionInfoType::Overloaded(infos) => { + let indices = infos .iter() .map(|info| (ArgumentSignature::from(info), 0)) - .collect(), - info: FunctionInfoType::Overloaded(infos), - }, + .collect(); + FunctionMap::Overloaded(vec![func], infos.into_owned(), indices) + } }, } } @@ -302,10 +296,10 @@ impl<'env> DynamicFunction<'env> { /// /// The function itself may also return any errors it needs to. pub fn call<'a>(&self, args: ArgList<'a>) -> FunctionResult<'a> { - let expected_arg_count = self.function_map.info.arg_count(); + let expected_arg_count = self.function_map.info().arg_count(); let received_arg_count = args.len(); - if matches!(self.function_map.info, FunctionInfoType::Standard(_)) + if matches!(self.function_map.info(), FunctionInfoType::Standard(_)) && expected_arg_count != received_arg_count { Err(FunctionError::ArgCountMismatch { @@ -319,8 +313,8 @@ impl<'env> DynamicFunction<'env> { } /// Returns the function info. - pub fn info(&self) -> &FunctionInfoType { - &self.function_map.info + pub fn info(&self) -> FunctionInfoType { + self.function_map.info() } /// The name of the function. @@ -347,8 +341,8 @@ impl Function for DynamicFunction<'static> { self.name.as_ref() } - fn info(&self) -> &FunctionInfoType { - &self.function_map.info + fn info(&self) -> FunctionInfoType { + self.function_map.info() } fn reflect_call<'a>(&self, args: ArgList<'a>) -> FunctionResult<'a> { diff --git a/crates/bevy_reflect/src/func/dynamic_function_mut.rs b/crates/bevy_reflect/src/func/dynamic_function_mut.rs index af92a21547..5f84fe58ae 100644 --- a/crates/bevy_reflect/src/func/dynamic_function_mut.rs +++ b/crates/bevy_reflect/src/func/dynamic_function_mut.rs @@ -8,7 +8,6 @@ use crate::func::{ args::ArgList, function_map::FunctionMap, signature::ArgumentSignature, DynamicFunction, FunctionError, FunctionInfoType, FunctionOverloadError, FunctionResult, IntoFunctionMut, }; -use bevy_utils::HashMap; /// A [`Box`] containing a callback to a reflected function. type BoxFnMut<'env> = Box FnMut(ArgList<'a>) -> FunctionResult<'a> + 'env>; @@ -93,7 +92,7 @@ impl<'env> DynamicFunctionMut<'env> { /// [function overloading]: Self::with_overload pub fn new FnMut(ArgList<'a>) -> FunctionResult<'a> + 'env>( func: F, - info: impl TryInto, + info: impl TryInto, Error: Debug>, ) -> Self { let info = info.try_into().unwrap(); @@ -105,19 +104,14 @@ impl<'env> DynamicFunctionMut<'env> { FunctionInfoType::Overloaded(_) => None, }, function_map: match info { - FunctionInfoType::Standard(info) => FunctionMap { - functions: vec![func], - indices: HashMap::from([(ArgumentSignature::from(&info), 0)]), - info: FunctionInfoType::Standard(info), - }, - FunctionInfoType::Overloaded(infos) => FunctionMap { - functions: vec![func], - indices: infos + FunctionInfoType::Standard(info) => FunctionMap::Single(func, info.into_owned()), + FunctionInfoType::Overloaded(infos) => { + let indices = infos .iter() .map(|info| (ArgumentSignature::from(info), 0)) - .collect(), - info: FunctionInfoType::Overloaded(infos), - }, + .collect(); + FunctionMap::Overloaded(vec![func], infos.into_owned(), indices) + } }, } } @@ -272,10 +266,10 @@ impl<'env> DynamicFunctionMut<'env> { /// /// [`call_once`]: DynamicFunctionMut::call_once pub fn call<'a>(&mut self, args: ArgList<'a>) -> FunctionResult<'a> { - let expected_arg_count = self.function_map.info.arg_count(); + let expected_arg_count = self.function_map.info().arg_count(); let received_arg_count = args.len(); - if matches!(self.function_map.info, FunctionInfoType::Standard(_)) + if matches!(self.function_map.info(), FunctionInfoType::Standard(_)) && expected_arg_count != received_arg_count { Err(FunctionError::ArgCountMismatch { @@ -321,8 +315,8 @@ impl<'env> DynamicFunctionMut<'env> { } /// Returns the function info. - pub fn info(&self) -> &FunctionInfoType { - &self.function_map.info + pub fn info(&self) -> FunctionInfoType { + self.function_map.info() } /// The name of the function. @@ -378,15 +372,13 @@ impl<'env> From> for DynamicFunctionMut<'env> { fn from(function: DynamicFunction<'env>) -> Self { Self { name: function.name, - function_map: FunctionMap { - info: function.function_map.info, - indices: function.function_map.indices, - functions: function - .function_map - .functions - .into_iter() - .map(arc_to_box) - .collect(), + function_map: match function.function_map { + FunctionMap::Single(func, info) => FunctionMap::Single(arc_to_box(func), info), + FunctionMap::Overloaded(funcs, infos, indices) => FunctionMap::Overloaded( + funcs.into_iter().map(arc_to_box).collect(), + infos, + indices, + ), }, } } diff --git a/crates/bevy_reflect/src/func/function.rs b/crates/bevy_reflect/src/func/function.rs index 5879d6660a..97a2c85d2b 100644 --- a/crates/bevy_reflect/src/func/function.rs +++ b/crates/bevy_reflect/src/func/function.rs @@ -53,7 +53,7 @@ pub trait Function: PartialReflect + Debug { } /// The [`FunctionInfoType`] for this function. - fn info(&self) -> &FunctionInfoType; + fn info(&self) -> FunctionInfoType; /// Call this function with the given arguments. fn reflect_call<'a>(&self, args: ArgList<'a>) -> FunctionResult<'a>; diff --git a/crates/bevy_reflect/src/func/function_map.rs b/crates/bevy_reflect/src/func/function_map.rs index 832598edeb..6a6942a93e 100644 --- a/crates/bevy_reflect/src/func/function_map.rs +++ b/crates/bevy_reflect/src/func/function_map.rs @@ -1,16 +1,16 @@ use crate::func::signature::ArgumentSignature; -use crate::func::{ArgList, FunctionError, FunctionInfoType, FunctionOverloadError}; +use crate::func::{ArgList, FunctionError, FunctionInfo, FunctionInfoType, FunctionOverloadError}; +use alloc::borrow::Cow; use bevy_utils::HashMap; /// A helper type for storing a mapping of overloaded functions /// along with the corresponding [function information]. /// -/// [function information]: FunctionInfoType +/// [function information]: FunctionInfo #[derive(Clone, Debug)] -pub(super) struct FunctionMap { - pub info: FunctionInfoType, - pub functions: Vec, - pub indices: HashMap, +pub(super) enum FunctionMap { + Single(F, FunctionInfo), + Overloaded(Vec, Vec, HashMap), } impl FunctionMap { @@ -21,17 +21,18 @@ impl FunctionMap { /// /// If no overload matches the provided arguments, an error will be returned. pub fn get(&self, args: &ArgList) -> Result<&F, FunctionError> { - if self.functions.len() == 1 { - Ok(&self.functions[0]) - } else { - let signature = ArgumentSignature::from(args); - self.indices - .get(&signature) - .map(|index| &self.functions[*index]) - .ok_or_else(|| FunctionError::NoOverload { - expected: self.indices.keys().cloned().collect(), - received: signature, - }) + match self { + Self::Single(function, _) => Ok(function), + Self::Overloaded(functions, _, indices) => { + let signature = ArgumentSignature::from(args); + indices + .get(&signature) + .map(|index| &functions[*index]) + .ok_or_else(|| FunctionError::NoOverload { + expected: indices.keys().cloned().collect(), + received: signature, + }) + } } } @@ -42,17 +43,26 @@ impl FunctionMap { /// /// If no overload matches the provided arguments, an error will be returned. pub fn get_mut(&mut self, args: &ArgList) -> Result<&mut F, FunctionError> { - if self.functions.len() == 1 { - Ok(&mut self.functions[0]) - } else { - let signature = ArgumentSignature::from(args); - self.indices - .get(&signature) - .map(|index| &mut self.functions[*index]) - .ok_or_else(|| FunctionError::NoOverload { - expected: self.indices.keys().cloned().collect(), - received: signature, - }) + match self { + Self::Single(function, _) => Ok(function), + Self::Overloaded(functions, _, indices) => { + let signature = ArgumentSignature::from(args); + indices + .get(&signature) + .map(|index| &mut functions[*index]) + .ok_or_else(|| FunctionError::NoOverload { + expected: indices.keys().cloned().collect(), + received: signature, + }) + } + } + } + + /// Returns the function information contained in the map. + pub fn info(&self) -> FunctionInfoType { + match self { + Self::Single(_, info) => FunctionInfoType::Standard(Cow::Borrowed(info)), + Self::Overloaded(_, info, _) => FunctionInfoType::Overloaded(Cow::Borrowed(info)), } } @@ -60,42 +70,97 @@ impl FunctionMap { /// /// If the other map contains any functions with the same signature as this one, /// an error will be returned along with the original, unchanged map. - pub fn merge(mut self, other: Self) -> Result, FunctionOverloadError)> { - // === Function Map === // - let mut other_indices = HashMap::new(); + pub fn merge(self, other: Self) -> Result, FunctionOverloadError)> { + match (self, other) { + (Self::Single(self_func, self_info), Self::Single(other_func, other_info)) => { + let self_sig = ArgumentSignature::from(&self_info); + let other_sig = ArgumentSignature::from(&other_info); + if self_sig == other_sig { + return Err(( + Box::new(Self::Single(self_func, self_info)), + FunctionOverloadError { + signature: self_sig, + }, + )); + } - for (sig, index) in other.indices { - if self.indices.contains_key(&sig) { - return Err((Box::new(self), FunctionOverloadError { signature: sig })); + Ok(Self::Overloaded( + vec![self_func, other_func], + vec![self_info, other_info], + HashMap::from([(self_sig, 0), (other_sig, 1)]), + )) } + ( + Self::Single(self_func, self_info), + Self::Overloaded(mut other_funcs, mut other_infos, mut other_indices), + ) => { + let self_sig = ArgumentSignature::from(&self_info); + if other_indices.contains_key(&self_sig) { + return Err(( + Box::new(Self::Single(self_func, self_info)), + FunctionOverloadError { + signature: self_sig, + }, + )); + } - other_indices.insert(sig, self.functions.len() + index); + for index in other_indices.values_mut() { + *index += 1; + } + + other_funcs.insert(0, self_func); + other_infos.insert(0, self_info); + other_indices.insert(self_sig, 0); + + Ok(Self::Overloaded(other_funcs, other_infos, other_indices)) + } + ( + Self::Overloaded(mut self_funcs, mut self_infos, mut self_indices), + Self::Single(other_func, other_info), + ) => { + let other_sig = ArgumentSignature::from(&other_info); + if self_indices.contains_key(&other_sig) { + return Err(( + Box::new(Self::Overloaded(self_funcs, self_infos, self_indices)), + FunctionOverloadError { + signature: other_sig, + }, + )); + } + + let index = self_funcs.len(); + self_funcs.push(other_func); + self_infos.push(other_info); + self_indices.insert(other_sig, index); + + Ok(Self::Overloaded(self_funcs, self_infos, self_indices)) + } + ( + Self::Overloaded(mut self_funcs, mut self_infos, mut self_indices), + Self::Overloaded(mut other_funcs, mut other_infos, other_indices), + ) => { + let mut new_indices = HashMap::new(); + + for (sig, index) in other_indices { + if self_indices.contains_key(&sig) { + return Err(( + Box::new(Self::Overloaded(self_funcs, self_infos, self_indices)), + FunctionOverloadError { signature: sig }, + )); + } + + new_indices.insert(sig, self_funcs.len() + index); + } + + self_indices.extend(new_indices); + self_funcs.append(&mut other_funcs); + // The index map and `FunctionInfo` list should always be in sync, + // so we can simply append the new infos to the existing ones. + self_infos.append(&mut other_infos); + + Ok(Self::Overloaded(self_funcs, self_infos, self_indices)) + } } - - // === Function Info === // - let mut other_infos = Vec::new(); - - for info in other.info.into_iter() { - let sig = ArgumentSignature::from(&info); - if self.indices.contains_key(&sig) { - return Err((Box::new(self), FunctionOverloadError { signature: sig })); - } - other_infos.push(info); - } - - // === Update === // - self.indices.extend(other_indices); - self.functions.extend(other.functions); - self.info = match self.info { - FunctionInfoType::Standard(info) => { - FunctionInfoType::Overloaded(std::iter::once(info).chain(other_infos).collect()) - } - FunctionInfoType::Overloaded(infos) => FunctionInfoType::Overloaded( - IntoIterator::into_iter(infos).chain(other_infos).collect(), - ), - }; - - Ok(self) } } @@ -106,100 +171,166 @@ mod tests { use crate::Type; #[test] - fn should_merge_function_maps() { - let map_a = FunctionMap { - info: FunctionInfoType::Overloaded(Box::new([ - FunctionInfo::anonymous().with_arg::("arg0"), - FunctionInfo::anonymous().with_arg::("arg0"), - FunctionInfo::anonymous().with_arg::("arg0"), - ])), - functions: vec!['a', 'b', 'c'], - indices: HashMap::from([ - (ArgumentSignature::from_iter([Type::of::()]), 0), - (ArgumentSignature::from_iter([Type::of::()]), 1), - (ArgumentSignature::from_iter([Type::of::()]), 2), - ]), - }; + fn should_merge_single_into_single() { + let map_a = FunctionMap::Single('a', FunctionInfo::anonymous().with_arg::("arg0")); + let map_b = FunctionMap::Single('b', FunctionInfo::anonymous().with_arg::("arg0")); - let map_b = FunctionMap { - info: FunctionInfoType::Overloaded(Box::new([ + let FunctionMap::Overloaded(functions, infos, indices) = map_a.merge(map_b).unwrap() else { + panic!("expected overloaded function"); + }; + assert_eq!(functions, vec!['a', 'b']); + assert_eq!(infos.len(), 2); + assert_eq!( + indices, + HashMap::from([ + (ArgumentSignature::from_iter([Type::of::()]), 0), + (ArgumentSignature::from_iter([Type::of::()]), 1), + ]) + ); + } + + #[test] + fn should_merge_single_into_overloaded() { + let map_a = FunctionMap::Single('a', FunctionInfo::anonymous().with_arg::("arg0")); + let map_b = FunctionMap::Overloaded( + vec!['b', 'c'], + vec![ FunctionInfo::anonymous().with_arg::("arg0"), FunctionInfo::anonymous().with_arg::("arg0"), - FunctionInfo::anonymous().with_arg::("arg0"), - ])), - functions: vec!['d', 'e', 'f'], - indices: HashMap::from([ + ], + HashMap::from([ (ArgumentSignature::from_iter([Type::of::()]), 0), (ArgumentSignature::from_iter([Type::of::()]), 1), - (ArgumentSignature::from_iter([Type::of::()]), 2), ]), + ); + + let FunctionMap::Overloaded(functions, infos, indices) = map_a.merge(map_b).unwrap() else { + panic!("expected overloaded function"); }; - - let map = map_a.merge(map_b).unwrap(); - - assert_eq!(map.functions, vec!['a', 'b', 'c', 'd', 'e', 'f']); + assert_eq!(functions, vec!['a', 'b', 'c']); + assert_eq!(infos.len(), 3); assert_eq!( - map.indices, + indices, + HashMap::from([ + (ArgumentSignature::from_iter([Type::of::()]), 0), + (ArgumentSignature::from_iter([Type::of::()]), 1), + (ArgumentSignature::from_iter([Type::of::()]), 2), + ]) + ); + } + + #[test] + fn should_merge_overloaed_into_single() { + let map_a = FunctionMap::Overloaded( + vec!['a', 'b'], + vec![ + FunctionInfo::anonymous().with_arg::("arg0"), + FunctionInfo::anonymous().with_arg::("arg0"), + ], HashMap::from([ (ArgumentSignature::from_iter([Type::of::()]), 0), (ArgumentSignature::from_iter([Type::of::()]), 1), - (ArgumentSignature::from_iter([Type::of::()]), 2), - (ArgumentSignature::from_iter([Type::of::()]), 3), - (ArgumentSignature::from_iter([Type::of::()]), 4), - (ArgumentSignature::from_iter([Type::of::()]), 5), + ]), + ); + let map_b = FunctionMap::Single('c', FunctionInfo::anonymous().with_arg::("arg0")); + + let FunctionMap::Overloaded(functions, infos, indices) = map_a.merge(map_b).unwrap() else { + panic!("expected overloaded function"); + }; + assert_eq!(functions, vec!['a', 'b', 'c']); + assert_eq!(infos.len(), 3); + assert_eq!( + indices, + HashMap::from([ + (ArgumentSignature::from_iter([Type::of::()]), 0), + (ArgumentSignature::from_iter([Type::of::()]), 1), + (ArgumentSignature::from_iter([Type::of::()]), 2), + ]) + ); + } + + #[test] + fn should_merge_overloaded_into_overloaded() { + let map_a = FunctionMap::Overloaded( + vec!['a', 'b'], + vec![ + FunctionInfo::anonymous().with_arg::("arg0"), + FunctionInfo::anonymous().with_arg::("arg0"), + ], + HashMap::from([ + (ArgumentSignature::from_iter([Type::of::()]), 0), + (ArgumentSignature::from_iter([Type::of::()]), 1), + ]), + ); + let map_b = FunctionMap::Overloaded( + vec!['c', 'd'], + vec![ + FunctionInfo::anonymous().with_arg::("arg0"), + FunctionInfo::anonymous().with_arg::("arg0"), + ], + HashMap::from([ + (ArgumentSignature::from_iter([Type::of::()]), 0), + (ArgumentSignature::from_iter([Type::of::()]), 1), + ]), + ); + + let FunctionMap::Overloaded(functions, infos, indices) = map_a.merge(map_b).unwrap() else { + panic!("expected overloaded function"); + }; + assert_eq!(functions, vec!['a', 'b', 'c', 'd']); + assert_eq!(infos.len(), 4); + assert_eq!( + indices, + HashMap::from([ + (ArgumentSignature::from_iter([Type::of::()]), 0), + (ArgumentSignature::from_iter([Type::of::()]), 1), + (ArgumentSignature::from_iter([Type::of::()]), 2), + (ArgumentSignature::from_iter([Type::of::()]), 3), ]) ); } #[test] fn should_return_error_on_duplicate_signature() { - let map_a = FunctionMap { - info: FunctionInfoType::Overloaded(Box::new([ - FunctionInfo::anonymous().with_arg::("arg0"), - FunctionInfo::anonymous().with_arg::("arg0"), - FunctionInfo::anonymous().with_arg::("arg0"), - ])), - functions: vec!['a', 'b', 'c'], - indices: HashMap::from([ - (ArgumentSignature::from_iter([Type::of::()]), 0), - (ArgumentSignature::from_iter([Type::of::()]), 1), - (ArgumentSignature::from_iter([Type::of::()]), 2), - ]), - }; - - let map_b = FunctionMap { - info: FunctionInfoType::Overloaded(Box::new([ + let map_a = FunctionMap::Single( + 'a', + FunctionInfo::anonymous() + .with_arg::("arg0") + .with_arg::("arg1"), + ); + let map_b = FunctionMap::Overloaded( + vec!['b', 'c'], + vec![ FunctionInfo::anonymous().with_arg::("arg0"), - FunctionInfo::anonymous().with_arg::("arg0"), - FunctionInfo::anonymous().with_arg::("arg0"), - ])), - functions: vec!['d', 'e', 'f'], - indices: HashMap::from([ - (ArgumentSignature::from_iter([Type::of::()]), 0), - (ArgumentSignature::from_iter([Type::of::()]), 1), - (ArgumentSignature::from_iter([Type::of::()]), 2), + FunctionInfo::anonymous().with_arg::("arg1"), + ], + HashMap::from([ + ( + ArgumentSignature::from_iter([Type::of::(), Type::of::()]), + 0, + ), + ( + ArgumentSignature::from_iter([Type::of::(), Type::of::()]), + 1, + ), ]), - }; - - let Err((map_a, error)) = map_a.merge(map_b) else { - panic!("expected an error"); - }; - assert_eq!( - error, - FunctionOverloadError { - signature: ArgumentSignature::from_iter([Type::of::()]) - } ); - // Assert that the original map remains unchanged: - assert_eq!(map_a.functions, vec!['a', 'b', 'c']); + let (map, error) = map_a.merge(map_b).unwrap_err(); assert_eq!( - map_a.indices, - HashMap::from([ - (ArgumentSignature::from_iter([Type::of::()]), 0), - (ArgumentSignature::from_iter([Type::of::()]), 1), - (ArgumentSignature::from_iter([Type::of::()]), 2), - ]) + error.signature, + ArgumentSignature::from_iter([Type::of::(), Type::of::()]) + ); + + // Assert the original map remains unchanged: + let FunctionMap::Single(function, info) = *map else { + panic!("expected single function"); + }; + + assert_eq!(function, 'a'); + assert_eq!( + ArgumentSignature::from(info), + ArgumentSignature::from_iter([Type::of::(), Type::of::()]) ); } } diff --git a/crates/bevy_reflect/src/func/info.rs b/crates/bevy_reflect/src/func/info.rs index 9a4d1e7929..f9da702d1f 100644 --- a/crates/bevy_reflect/src/func/info.rs +++ b/crates/bevy_reflect/src/func/info.rs @@ -17,49 +17,51 @@ use crate::{ /// A wrapper around [`FunctionInfo`] used to represent either a standard function /// or an overloaded function. #[derive(Debug, Clone)] -pub enum FunctionInfoType { +pub enum FunctionInfoType<'a> { /// A standard function with a single set of arguments. /// /// This includes generic functions with a single set of monomorphized arguments. - Standard(FunctionInfo), + Standard(Cow<'a, FunctionInfo>), /// An overloaded function with multiple sets of arguments. /// /// This includes generic functions with multiple sets of monomorphized arguments, /// as well as functions with a variable number of arguments (i.e. "variadic functions"). - Overloaded(Box<[FunctionInfo]>), + Overloaded(Cow<'a, [FunctionInfo]>), } -impl From for FunctionInfoType { +impl From for FunctionInfoType<'_> { fn from(info: FunctionInfo) -> Self { - FunctionInfoType::Standard(info) + FunctionInfoType::Standard(Cow::Owned(info)) } } -impl TryFrom> for FunctionInfoType { +impl TryFrom> for FunctionInfoType<'_> { type Error = MissingFunctionInfoError; fn try_from(mut infos: Vec) -> Result { match infos.len() { 0 => Err(MissingFunctionInfoError), - 1 => Ok(Self::Standard(infos.pop().unwrap())), - _ => Ok(Self::Overloaded(infos.into_boxed_slice())), + 1 => Ok(Self::Standard(Cow::Owned(infos.pop().unwrap()))), + _ => Ok(Self::Overloaded(Cow::Owned(infos))), } } } -impl IntoIterator for FunctionInfoType { +impl IntoIterator for FunctionInfoType<'_> { type Item = FunctionInfo; type IntoIter = vec::IntoIter; fn into_iter(self) -> Self::IntoIter { + // Allow `.into_owned()` so that we can create a `std::vec::IntoIter` + #[allow(clippy::unnecessary_to_owned)] match self { - FunctionInfoType::Standard(info) => vec![info].into_iter(), - FunctionInfoType::Overloaded(infos) => infos.into_vec().into_iter(), + FunctionInfoType::Standard(info) => vec![info.into_owned()].into_iter(), + FunctionInfoType::Overloaded(infos) => infos.into_owned().into_iter(), } } } -impl FunctionInfoType { +impl FunctionInfoType<'_> { pub fn arg_count(&self) -> usize { match self { Self::Standard(info) => info.arg_count(),