@@ -14,27 +14,41 @@ use std::ffi::CStr;
1414/// An `impl AsArg<T>` parameter allows values to be passed which can be represented in the target type `T`. Note that unlike `From<T>`,
1515/// this trait is implemented more conservatively.
1616///
17+ /// As a result, `AsArg<T>` is currently only implemented for certain argument types:
18+ /// - `T` for by-value builtins (typically `Copy`): `i32`, `bool`, `Vector3`, `Transform2D`, ...
19+ /// - `&T` for by-ref builtins: `GString`, `Array`, `Dictionary`, `Packed*Array`, `Variant`...
20+ /// - `&str`, `&String` additionally for string types `GString`, `StringName`, `NodePath`.
21+ ///
22+ /// # Pass by value
23+ /// Implicitly converting from `T` for by-ref builtins is explicitly not supported. This emphasizes that there is no need to consume the object,
24+ /// thus discourages unnecessary cloning.
25+ ///
26+ /// If you need to pass owned values in generic code, you can use [`DeclParam::value_to_arg()`].
27+ ///
1728/// # Performance for strings
1829/// Godot has three string types: [`GString`], [`StringName`] and [`NodePath`]. Conversions between those three, as well as between `String` and
1930/// them, is generally expensive because of allocations, re-encoding, validations, hashing, etc. While this doesn't matter for a few strings
2031/// passed to engine APIs, it can become a problematic when passing long strings in a hot loop.
2132///
22- /// As a result, `AsArg<T>` is currently only implemented for certain conversions:
23- /// - `&T` and `&mut T`, since those require no conversion or copy.
24- /// - String literals like `"string"` and `c"string"`. While these _do_ need conversions, those are quite explicit, and
25- /// `&'static CStr -> StringName` in particular is cheap.
33+ /// In the case of strings, we allow implicit conversion from Rust types `&str`, `&String` and `&'static CStr` (`StringName` only).
34+ /// While these conversions are not free, those are either explicit because a string literal is used, or they are unsurprising, because Godot
35+ /// cannot deal with raw Rust types. On the other hand, `GString` and `StringName` are sometimes used almost interchangeably (example:
36+ /// [`Node::set_name`](crate::classes::Node::set_name) takes `GString` but [`Node::get_name`](crate::classes::Node::get_name) returns `StringName`).
37+ ///
38+ /// If you want to convert between Godot's string types for the sake of argument passing, each type provides an `arg()` method, such as
39+ /// [`GString::arg()`]. You cannot use this method in other contexts.
2640#[ diagnostic:: on_unimplemented(
2741 message = "Argument of type `{Self}` cannot be passed to an `impl AsArg<{T}>` parameter" ,
2842 note = "If you pass by value, consider borrowing instead." ,
2943 note = "GString/StringName/NodePath aren't implicitly convertible for performance reasons; use their `arg()` method." ,
3044 note = "See also `AsArg` docs: https://godot-rust.github.io/docs/gdext/master/godot/meta/trait.AsArg.html"
3145) ]
32- pub trait AsArg < T : ArgTarget >
46+ pub trait AsArg < T : DeclParam >
3347where
3448 Self : Sized ,
3549{
3650 #[ doc( hidden) ]
37- fn into_arg < ' r > ( self ) -> <T as ArgTarget >:: Type < ' r >
51+ fn into_arg < ' r > ( self ) -> <T as DeclParam >:: Arg < ' r >
3852 where
3953 Self : ' r ;
4054}
@@ -56,7 +70,7 @@ macro_rules! arg_into_ref {
5670 } ;
5771 ( $arg_variable: ident: $T: ty) => {
5872 let $arg_variable = $arg_variable. into_arg( ) ;
59- let $arg_variable: & $T = $crate:: meta:: ArgTarget :: arg_to_ref( & $arg_variable) ;
73+ let $arg_variable: & $T = $crate:: meta:: DeclParam :: arg_to_ref( & $arg_variable) ;
6074 } ;
6175}
6276
@@ -76,20 +90,20 @@ macro_rules! arg_into_owned {
7690macro_rules! impl_asarg_by_value {
7791 ( $T: ty) => {
7892 impl $crate:: meta:: AsArg <$T> for $T {
79- fn into_arg<' r>( self ) -> <$T as $crate:: meta:: ArgTarget >:: Type <' r> {
93+ fn into_arg<' r>( self ) -> <$T as $crate:: meta:: DeclParam >:: Arg <' r> {
8094 // Moves value (but typically a Copy type).
8195 self
8296 }
8397 }
8498
85- impl $crate:: meta:: ArgTarget for $T {
86- type Type <' v> = $T;
99+ impl $crate:: meta:: DeclParam for $T {
100+ type Arg <' v> = $T;
87101
88- fn value_to_arg<' v>( self ) -> Self :: Type <' v> {
102+ fn value_to_arg<' v>( self ) -> Self :: Arg <' v> {
89103 self
90104 }
91105
92- fn arg_to_ref<' r>( arg: & ' r Self :: Type <' _>) -> & ' r Self {
106+ fn arg_to_ref<' r>( arg: & ' r Self :: Arg <' _>) -> & ' r Self {
93107 arg
94108 }
95109 }
@@ -107,22 +121,22 @@ macro_rules! impl_asarg_by_ref {
107121 // Thus, keep `where` on same line.
108122 // type ArgType<'v> = &'v $T where Self: 'v;
109123
110- fn into_arg<' cow>( self ) -> <$T as $crate:: meta:: ArgTarget >:: Type <' cow>
124+ fn into_arg<' cow>( self ) -> <$T as $crate:: meta:: DeclParam >:: Arg <' cow>
111125 where
112126 ' r: ' cow, // Original reference must be valid for at least as long as the returned cow.
113127 {
114128 $crate:: meta:: CowArg :: Borrowed ( self )
115129 }
116130 }
117131
118- impl $crate:: meta:: ArgTarget for $T {
119- type Type <' v> = $crate:: meta:: CowArg <' v, $T>;
132+ impl $crate:: meta:: DeclParam for $T {
133+ type Arg <' v> = $crate:: meta:: CowArg <' v, $T>;
120134
121- fn value_to_arg<' v>( self ) -> Self :: Type <' v> {
135+ fn value_to_arg<' v>( self ) -> Self :: Arg <' v> {
122136 $crate:: meta:: CowArg :: Owned ( self )
123137 }
124138
125- fn arg_to_ref<' r>( arg: & ' r Self :: Type <' _>) -> & ' r Self {
139+ fn arg_to_ref<' r>( arg: & ' r Self :: Arg <' _>) -> & ' r Self {
126140 arg. cow_as_ref( )
127141 }
128142 }
@@ -136,11 +150,11 @@ macro_rules! declare_arg_method {
136150 ///
137151 /// # Generic bounds
138152 /// The bounds are implementation-defined and may change at any time. Do not use this function in a generic context requiring `T`
139- /// -- use the `From` trait in that case.
153+ /// -- use the `From` trait or [`DeclParam`][crate::meta::DeclParam] in that case.
140154 pub fn arg<T >( & self ) -> impl $crate:: meta:: AsArg <T >
141155 where
142156 for <' a> T : From <& ' a Self >
143- + $crate:: meta:: ArgTarget < Type <' a> = $crate:: meta:: CowArg <' a, T >>
157+ + $crate:: meta:: DeclParam < Arg <' a> = $crate:: meta:: CowArg <' a, T >>
144158 + ' a,
145159 {
146160 $crate:: meta:: CowArg :: Owned ( T :: from( self ) )
@@ -157,7 +171,7 @@ macro_rules! declare_arg_method {
157171/// This is necessary for packed array dispatching to different "inner" backend signatures.
158172impl < ' a , T > AsArg < T > for CowArg < ' a , T >
159173where
160- for < ' r > T : ArgTarget < Type < ' r > = CowArg < ' r , T > > + ' r ,
174+ for < ' r > T : DeclParam < Arg < ' r > = CowArg < ' r , T > > + ' r ,
161175{
162176 fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
163177 where
@@ -228,32 +242,28 @@ impl AsArg<NodePath> for &String {
228242
229243// ----------------------------------------------------------------------------------------------------------------------------------------------
230244
231- /// Implemented for all types that can be stored in [ `AsArg<T>`].
232- pub trait ArgTarget
245+ /// Implemented for all parameter types `T` that are allowed to receive [impl `AsArg<T>`][AsArg]` .
246+ pub trait DeclParam
233247where
234248 Self : Sized ,
235249{
236- /// Target type, either `T` or `CowArg<'v, T>` .
250+ /// Canonical argument passing type, either `T` or an internally-used CoW type .
237251 ///
238252 /// The general rule is that `Copy` types are passed by value, while the rest is passed by reference.
239253 ///
240- /// This associated type is closely related to [`ToGodot::ToVia<'v>`] and may be reorganized.
241- type Type < ' v > : AsArg < Self >
254+ /// This associated type is closely related to [`ToGodot::ToVia<'v>`][crate::meta::ToGodot::ToVia] and may be reorganized.
255+ type Arg < ' v > : AsArg < Self >
242256 where
243257 Self : ' v ;
244258
245- /// Converts an owned value to the canonical argument type.
259+ /// Converts an owned value to the canonical argument type, which can be passed to [`impl AsArg<T>`][AsArg] .
246260 ///
247261 /// Useful in generic contexts where only a value is available, and one doesn't want to dispatch between value/reference.
248- #[ doc( hidden) ]
249- fn value_to_arg < ' v > ( self ) -> Self :: Type < ' v > ;
262+ fn value_to_arg < ' v > ( self ) -> Self :: Arg < ' v > ;
250263
251- /// Converts an owned value to the canonical argument type .
264+ /// Converts an argument to a shared reference .
252265 ///
253- /// Useful in generic contexts where only a value is available, and one doesn't want to dispatch between value/reference .
254- #[ doc( hidden) ]
255- fn arg_to_ref < ' r > ( arg : & ' r Self :: Type < ' _ > ) -> & ' r Self ;
266+ /// Useful in generic contexts where you need to extract a reference of an argument, independently of how it is passed .
267+ #[ doc( hidden) ] // for now, users are encouraged to use only call-site of impl AsArg; declaration-site may still develop.
268+ fn arg_to_ref < ' r > ( arg : & ' r Self :: Arg < ' _ > ) -> & ' r Self ;
256269}
257-
258- /// Shorthand to determine how a type is passed as an argument to Godot APIs.
259- pub type Arg < ' r , T > = <T as ArgTarget >:: Type < ' r > ;
0 commit comments