@@ -14,15 +14,29 @@ use std::ffi::CStr;
14
14
/// An `impl AsArg<T>` parameter allows values to be passed which can be represented in the target type `T`. Note that unlike `From<T>`,
15
15
/// this trait is implemented more conservatively.
16
16
///
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 [`ArgTarget::value_to_arg()`].
27
+ ///
17
28
/// # Performance for strings
18
29
/// Godot has three string types: [`GString`], [`StringName`] and [`NodePath`]. Conversions between those three, as well as between `String` and
19
30
/// them, is generally expensive because of allocations, re-encoding, validations, hashing, etc. While this doesn't matter for a few strings
20
31
/// passed to engine APIs, it can become a problematic when passing long strings in a hot loop.
21
32
///
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.
26
40
#[ diagnostic:: on_unimplemented(
27
41
message = "Argument of type `{Self}` cannot be passed to an `impl AsArg<{T}>` parameter" ,
28
42
note = "If you pass by value, consider borrowing instead." ,
34
48
Self : Sized ,
35
49
{
36
50
#[ doc( hidden) ]
37
- fn into_arg < ' r > ( self ) -> <T as ArgTarget >:: Type < ' r >
51
+ fn into_arg < ' r > ( self ) -> <T as ArgTarget >:: Arg < ' r >
38
52
where
39
53
Self : ' r ;
40
54
}
@@ -76,20 +90,20 @@ macro_rules! arg_into_owned {
76
90
macro_rules! impl_asarg_by_value {
77
91
( $T: ty) => {
78
92
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:: ArgTarget >:: Arg <' r> {
80
94
// Moves value (but typically a Copy type).
81
95
self
82
96
}
83
97
}
84
98
85
99
impl $crate:: meta:: ArgTarget for $T {
86
- type Type <' v> = $T;
100
+ type Arg <' v> = $T;
87
101
88
- fn value_to_arg<' v>( self ) -> Self :: Type <' v> {
102
+ fn value_to_arg<' v>( self ) -> Self :: Arg <' v> {
89
103
self
90
104
}
91
105
92
- fn arg_to_ref<' r>( arg: & ' r Self :: Type <' _>) -> & ' r Self {
106
+ fn arg_to_ref<' r>( arg: & ' r Self :: Arg <' _>) -> & ' r Self {
93
107
arg
94
108
}
95
109
}
@@ -107,7 +121,7 @@ macro_rules! impl_asarg_by_ref {
107
121
// Thus, keep `where` on same line.
108
122
// type ArgType<'v> = &'v $T where Self: 'v;
109
123
110
- fn into_arg<' cow>( self ) -> <$T as $crate:: meta:: ArgTarget >:: Type <' cow>
124
+ fn into_arg<' cow>( self ) -> <$T as $crate:: meta:: ArgTarget >:: Arg <' cow>
111
125
where
112
126
' r: ' cow, // Original reference must be valid for at least as long as the returned cow.
113
127
{
@@ -116,13 +130,13 @@ macro_rules! impl_asarg_by_ref {
116
130
}
117
131
118
132
impl $crate:: meta:: ArgTarget for $T {
119
- type Type <' v> = $crate:: meta:: CowArg <' v, $T>;
133
+ type Arg <' v> = $crate:: meta:: CowArg <' v, $T>;
120
134
121
- fn value_to_arg<' v>( self ) -> Self :: Type <' v> {
135
+ fn value_to_arg<' v>( self ) -> Self :: Arg <' v> {
122
136
$crate:: meta:: CowArg :: Owned ( self )
123
137
}
124
138
125
- fn arg_to_ref<' r>( arg: & ' r Self :: Type <' _>) -> & ' r Self {
139
+ fn arg_to_ref<' r>( arg: & ' r Self :: Arg <' _>) -> & ' r Self {
126
140
arg. cow_as_ref( )
127
141
}
128
142
}
@@ -136,11 +150,11 @@ macro_rules! declare_arg_method {
136
150
///
137
151
/// # Generic bounds
138
152
/// 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 [`ArgTarget`][crate::meta::ArgTarget] in that case.
140
154
pub fn arg<T >( & self ) -> impl $crate:: meta:: AsArg <T >
141
155
where
142
156
for <' a> T : From <& ' a Self >
143
- + $crate:: meta:: ArgTarget <Type <' a> = $crate:: meta:: CowArg <' a, T >>
157
+ + $crate:: meta:: ArgTarget <Arg <' a> = $crate:: meta:: CowArg <' a, T >>
144
158
+ ' a,
145
159
{
146
160
$crate:: meta:: CowArg :: Owned ( T :: from( self ) )
@@ -157,7 +171,7 @@ macro_rules! declare_arg_method {
157
171
/// This is necessary for packed array dispatching to different "inner" backend signatures.
158
172
impl < ' a , T > AsArg < T > for CowArg < ' a , T >
159
173
where
160
- for < ' r > T : ArgTarget < Type < ' r > = CowArg < ' r , T > > + ' r ,
174
+ for < ' r > T : ArgTarget < Arg < ' r > = CowArg < ' r , T > > + ' r ,
161
175
{
162
176
fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
163
177
where
@@ -228,32 +242,28 @@ impl AsArg<NodePath> for &String {
228
242
229
243
// ----------------------------------------------------------------------------------------------------------------------------------------------
230
244
231
- /// Implemented for all types that can be stored in [ `AsArg<T>`].
245
+ /// Implemented for all parameter types `T` that are allowed to receive [impl `AsArg<T>`][AsArg ].
232
246
pub trait ArgTarget
233
247
where
234
248
Self : Sized ,
235
249
{
236
- /// Target type, either `T` or `CowArg<'v, T>` .
250
+ /// Canonical argument passing type, either `T` or an internally-used CoW type .
237
251
///
238
252
/// The general rule is that `Copy` types are passed by value, while the rest is passed by reference.
239
253
///
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 >
242
256
where
243
257
Self : ' v ;
244
258
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] .
246
260
///
247
261
/// 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 > ;
250
263
251
- /// Converts an owned value to the canonical argument type .
264
+ /// Converts an argument to a shared reference .
252
265
///
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 ;
256
269
}
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