diff --git a/godot-core/src/builtin/collections/array.rs b/godot-core/src/builtin/collections/array.rs index a9c1a55ef..ffe1fe812 100644 --- a/godot-core/src/builtin/collections/array.rs +++ b/godot-core/src/builtin/collections/array.rs @@ -12,8 +12,8 @@ use crate::builtin::*; use crate::meta; use crate::meta::error::{ConvertError, FromGodotError, FromVariantError}; use crate::meta::{ - ArgTarget, ArrayElement, ArrayTypeInfo, AsArg, CowArg, FromGodot, GodotConvert, - GodotFfiVariant, GodotType, PropertyHintInfo, RefArg, ToGodot, + ApiParam, ArrayElement, ArrayTypeInfo, AsArg, CowArg, FromGodot, GodotConvert, GodotFfiVariant, + GodotType, PropertyHintInfo, RefArg, ToGodot, }; use crate::registry::property::{Export, Var}; use godot_ffi as sys; @@ -944,7 +944,7 @@ impl<'r, T: ArrayElement> AsArg> for &'r Array { } } -impl ArgTarget for Array { +impl ApiParam for Array { type Arg<'v> = CowArg<'v, Self>; fn value_to_arg<'v>(self) -> Self::Arg<'v> { @@ -1221,7 +1221,7 @@ impl Extend for Array { // A faster implementation using `resize()` and direct pointer writes might still be possible. // Note that this could technically also use iter(), since no moves need to happen (however Extend requires IntoIterator). for item in iter.into_iter() { - self.push(ArgTarget::value_to_arg(item)); + self.push(ApiParam::value_to_arg(item)); } } } diff --git a/godot-core/src/builtin/collections/packed_array.rs b/godot-core/src/builtin/collections/packed_array.rs index 8a7a0e67a..4347b6e65 100644 --- a/godot-core/src/builtin/collections/packed_array.rs +++ b/godot-core/src/builtin/collections/packed_array.rs @@ -491,7 +491,7 @@ macro_rules! impl_packed_array { // A faster implementation using `resize()` and direct pointer writes might still be // possible. for item in iter.into_iter() { - self.push(meta::ArgTarget::value_to_arg(item)); + self.push(meta::ApiParam::value_to_arg(item)); } } } diff --git a/godot-core/src/meta/as_arg.rs b/godot-core/src/meta/as_arg.rs index c24481786..c96192b82 100644 --- a/godot-core/src/meta/as_arg.rs +++ b/godot-core/src/meta/as_arg.rs @@ -6,7 +6,7 @@ */ use crate::builtin::{GString, NodePath, StringName}; -use crate::meta::CowArg; +use crate::meta::{CowArg, GodotType}; use std::ffi::CStr; /// Implicit conversions for arguments passed to Godot APIs. @@ -23,7 +23,7 @@ use std::ffi::CStr; /// Implicitly converting from `T` for by-ref builtins is explicitly not supported. This emphasizes that there is no need to consume the object, /// thus discourages unnecessary cloning. /// -/// If you need to pass owned values in generic code, you can use [`ArgTarget::value_to_arg()`]. +/// If you need to pass owned values in generic code, you can use [`ApiParam::value_to_arg()`]. /// /// # Performance for strings /// Godot has three string types: [`GString`], [`StringName`] and [`NodePath`]. Conversions between those three, as well as between `String` and @@ -37,18 +37,25 @@ use std::ffi::CStr; /// /// If you want to convert between Godot's string types for the sake of argument passing, each type provides an `arg()` method, such as /// [`GString::arg()`]. You cannot use this method in other contexts. +/// +/// # Using the trait +/// `AsArg` is meant to be used from the function call site, not the declaration site. If you declare a parameter as `impl AsArg<...>` yourself, +/// you can only forward it as-is to a Godot API -- there are no stable APIs to access the inner object yet. +/// +/// Furthermore, there is currently no benefit in implementing `AsArg` for your own types, as it's only used by Godot APIs which don't accept +/// custom types. Classes are already supported through upcasting and [`AsObjectArg`][crate::obj::AsObjectArg]. #[diagnostic::on_unimplemented( message = "Argument of type `{Self}` cannot be passed to an `impl AsArg<{T}>` parameter", note = "If you pass by value, consider borrowing instead.", note = "GString/StringName/NodePath aren't implicitly convertible for performance reasons; use their `arg()` method.", note = "See also `AsArg` docs: https://godot-rust.github.io/docs/gdext/master/godot/meta/trait.AsArg.html" )] -pub trait AsArg +pub trait AsArg where Self: Sized, { #[doc(hidden)] - fn into_arg<'r>(self) -> ::Arg<'r> + fn into_arg<'r>(self) -> ::Arg<'r> where Self: 'r; } @@ -70,7 +77,7 @@ macro_rules! arg_into_ref { }; ($arg_variable:ident: $T:ty) => { let $arg_variable = $arg_variable.into_arg(); - let $arg_variable: &$T = $crate::meta::ArgTarget::arg_to_ref(&$arg_variable); + let $arg_variable: &$T = $crate::meta::ApiParam::arg_to_ref(&$arg_variable); }; } @@ -82,7 +89,7 @@ macro_rules! arg_into_owned { ($arg_variable:ident) => { let $arg_variable = $arg_variable.into_arg(); let $arg_variable = $arg_variable.cow_into_owned(); - // cow_into_owned() is not yet used generically; could be abstracted in ArgTarget::arg_to_owned() as well. + // cow_into_owned() is not yet used generically; could be abstracted in ApiParam::arg_to_owned() as well. }; } @@ -90,13 +97,13 @@ macro_rules! arg_into_owned { macro_rules! impl_asarg_by_value { ($T:ty) => { impl $crate::meta::AsArg<$T> for $T { - fn into_arg<'r>(self) -> <$T as $crate::meta::ArgTarget>::Arg<'r> { + fn into_arg<'r>(self) -> <$T as $crate::meta::ApiParam>::Arg<'r> { // Moves value (but typically a Copy type). self } } - impl $crate::meta::ArgTarget for $T { + impl $crate::meta::ApiParam for $T { type Arg<'v> = $T; fn value_to_arg<'v>(self) -> Self::Arg<'v> { @@ -121,7 +128,7 @@ macro_rules! impl_asarg_by_ref { // Thus, keep `where` on same line. // type ArgType<'v> = &'v $T where Self: 'v; - fn into_arg<'cow>(self) -> <$T as $crate::meta::ArgTarget>::Arg<'cow> + fn into_arg<'cow>(self) -> <$T as $crate::meta::ApiParam>::Arg<'cow> where 'r: 'cow, // Original reference must be valid for at least as long as the returned cow. { @@ -129,7 +136,7 @@ macro_rules! impl_asarg_by_ref { } } - impl $crate::meta::ArgTarget for $T { + impl $crate::meta::ApiParam for $T { type Arg<'v> = $crate::meta::CowArg<'v, $T>; fn value_to_arg<'v>(self) -> Self::Arg<'v> { @@ -150,11 +157,11 @@ macro_rules! declare_arg_method { /// /// # Generic bounds /// The bounds are implementation-defined and may change at any time. Do not use this function in a generic context requiring `T` - /// -- use the `From` trait or [`ArgTarget`][crate::meta::ArgTarget] in that case. + /// -- use the `From` trait or [`ApiParam`][crate::meta::ApiParam] in that case. pub fn arg(&self) -> impl $crate::meta::AsArg where for<'a> T: From<&'a Self> - + $crate::meta::ArgTarget = $crate::meta::CowArg<'a, T>> + + $crate::meta::ApiParam = $crate::meta::CowArg<'a, T>> + 'a, { $crate::meta::CowArg::Owned(T::from(self)) @@ -171,7 +178,7 @@ macro_rules! declare_arg_method { /// This is necessary for packed array dispatching to different "inner" backend signatures. impl<'a, T> AsArg for CowArg<'a, T> where - for<'r> T: ArgTarget = CowArg<'r, T>> + 'r, + for<'r> T: ApiParam = CowArg<'r, T>> + 'r, { fn into_arg<'r>(self) -> CowArg<'r, T> where @@ -181,7 +188,7 @@ where } } -// impl<'a, T> ArgTarget for CowArg<'a, T> { +// impl<'a, T> ApiParam for CowArg<'a, T> { // type Type<'v> = CowArg<'v, T> // where Self: 'v; // } @@ -243,7 +250,8 @@ impl AsArg for &String { // ---------------------------------------------------------------------------------------------------------------------------------------------- /// Implemented for all parameter types `T` that are allowed to receive [impl `AsArg`][AsArg]. -pub trait ArgTarget +pub trait ApiParam: GodotType +// GodotType bound not required right now, but conceptually should always be the case. where Self: Sized, { diff --git a/godot-core/src/meta/cow_arg.rs b/godot-core/src/meta/cow_arg.rs index 6faa15d73..34b7834f6 100644 --- a/godot-core/src/meta/cow_arg.rs +++ b/godot-core/src/meta/cow_arg.rs @@ -47,7 +47,7 @@ impl<'r, T> CowArg<'r, T> { } } -/// Exists for polymorphism in [`crate::meta::ArgTarget`]. +/// Exists for polymorphism in [`crate::meta::ApiParam`]. /// /// Necessary for generics in e.g. `Array`, when accepting `impl AsArg` parameters. /// diff --git a/godot-core/src/meta/traits.rs b/godot-core/src/meta/traits.rs index b865db9d4..5c28f5cda 100644 --- a/godot-core/src/meta/traits.rs +++ b/godot-core/src/meta/traits.rs @@ -162,7 +162,7 @@ pub trait GodotType: GodotConvert + sealed::Sealed + Sized + 'static message = "`Array` can only store element types supported in Godot arrays (no nesting).", label = "has invalid element type" )] -pub trait ArrayElement: GodotType + ToGodot + FromGodot + sealed::Sealed + meta::ArgTarget { +pub trait ArrayElement: GodotType + ToGodot + FromGodot + sealed::Sealed + meta::ApiParam { /// Returns the representation of this type as a type string. /// /// Used for elements in arrays (the latter despite `ArrayElement` not having a direct relation). diff --git a/godot-core/src/obj/gd.rs b/godot-core/src/obj/gd.rs index 7f4563392..a862c70a5 100644 --- a/godot-core/src/obj/gd.rs +++ b/godot-core/src/obj/gd.rs @@ -16,7 +16,7 @@ use crate::builtin::{Callable, NodePath, StringName, Variant}; use crate::global::PropertyHint; use crate::meta::error::{ConvertError, FromFfiError}; use crate::meta::{ - ArgTarget, ArrayElement, AsArg, CallContext, ClassName, CowArg, FromGodot, GodotConvert, + ApiParam, ArrayElement, AsArg, CallContext, ClassName, CowArg, FromGodot, GodotConvert, GodotType, PropertyHintInfo, RefArg, ToGodot, }; use crate::obj::{ @@ -781,7 +781,7 @@ impl<'r, T: GodotClass> AsArg> for &'r Gd { } } -impl ArgTarget for Gd { +impl ApiParam for Gd { type Arg<'v> = CowArg<'v, Gd>; fn value_to_arg<'v>(self) -> Self::Arg<'v> { @@ -803,7 +803,7 @@ impl<'r, T: GodotClass> AsArg>> for Option<&'r Gd> { } } -impl ArgTarget for Option> { +impl ApiParam for Option> { type Arg<'v> = CowArg<'v, Option>>; fn value_to_arg<'v>(self) -> Self::Arg<'v> {