6
6
*/
7
7
8
8
use crate :: builtin:: { GString , NodePath , StringName } ;
9
- use crate :: meta:: { sealed, CowArg } ;
9
+ use crate :: meta:: { sealed, CowArg , ToGodot } ;
10
10
use std:: ffi:: CStr ;
11
11
12
12
/// Implicit conversions for arguments passed to Godot APIs.
@@ -53,16 +53,37 @@ use std::ffi::CStr;
53
53
note = "GString/StringName/NodePath aren't implicitly convertible for performance reasons; use their `arg()` method." ,
54
54
note = "see also `AsArg` docs: https://godot-rust.github.io/docs/gdext/master/godot/meta/trait.AsArg.html"
55
55
) ]
56
- pub trait AsArg < T : ParamType >
56
+ pub trait AsArg < T : ToGodot >
57
57
where
58
58
Self : Sized ,
59
59
{
60
+ // The usage of the CowArg return type introduces a small runtime penalty for values that implement Copy. Currently, the usage
61
+ // ergonomics out weigh the runtime cost. Using the CowArg allows us to create a blanket implementation of the trait for all types that
62
+ // implement ToGodot.
60
63
#[ doc( hidden) ]
61
- fn into_arg < ' r > ( self ) -> < T as ParamType > :: Arg < ' r >
64
+ fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
62
65
where
63
66
Self : ' r ;
64
67
}
65
68
69
+ impl < T : ToGodot > AsArg < T > for & T {
70
+ fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
71
+ where
72
+ Self : ' r ,
73
+ {
74
+ CowArg :: Borrowed ( self )
75
+ }
76
+ }
77
+
78
+ impl < T : ToGodot + Copy > AsArg < T > for T {
79
+ fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
80
+ where
81
+ Self : ' r ,
82
+ {
83
+ CowArg :: Owned ( self )
84
+ }
85
+ }
86
+
66
87
// ----------------------------------------------------------------------------------------------------------------------------------------------
67
88
// Blanket impls
68
89
@@ -81,7 +102,7 @@ macro_rules! arg_into_ref {
81
102
} ;
82
103
( $arg_variable: ident: $T: ty) => {
83
104
let $arg_variable = $arg_variable. into_arg( ) ;
84
- let $arg_variable: & $T = $crate :: meta :: ParamType :: arg_to_ref ( & $ arg_variable) ;
105
+ let $arg_variable: & $T = $arg_variable. cow_as_ref ( ) ;
85
106
} ;
86
107
}
87
108
@@ -102,20 +123,13 @@ macro_rules! arg_into_owned {
102
123
} ;
103
124
( infer $arg_variable: ident) => {
104
125
let $arg_variable = $arg_variable. into_arg( ) ;
105
- let $arg_variable = $crate :: meta :: ParamType :: arg_into_owned ( $ arg_variable) ;
126
+ let $arg_variable = $arg_variable. cow_into_owned ( ) ;
106
127
} ;
107
128
}
108
129
109
130
#[ macro_export]
110
131
macro_rules! impl_asarg_by_value {
111
132
( $T: ty) => {
112
- impl $crate:: meta:: AsArg <$T> for $T {
113
- fn into_arg<' r>( self ) -> <$T as $crate:: meta:: ParamType >:: Arg <' r> {
114
- // Moves value (but typically a Copy type).
115
- self
116
- }
117
- }
118
-
119
133
impl $crate:: meta:: ParamType for $T {
120
134
type Arg <' v> = $T;
121
135
@@ -137,22 +151,6 @@ macro_rules! impl_asarg_by_value {
137
151
#[ macro_export]
138
152
macro_rules! impl_asarg_by_ref {
139
153
( $T: ty) => {
140
- impl <' r> $crate:: meta:: AsArg <$T> for & ' r $T {
141
- // 1 rustfmt + 1 rustc problems (bugs?) here:
142
- // - formatting doesn't converge; `where` keeps being further indented on each run.
143
- // - a #[rustfmt::skip] annotation over the macro causes a compile error when mentioning `crate::impl_asarg_by_ref`.
144
- // "macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths"
145
- // Thus, keep `where` on same line.
146
- // type ArgType<'v> = &'v $T where Self: 'v;
147
-
148
- fn into_arg<' cow>( self ) -> <$T as $crate:: meta:: ParamType >:: Arg <' cow>
149
- where
150
- ' r: ' cow, // Original reference must be valid for at least as long as the returned cow.
151
- {
152
- $crate:: meta:: CowArg :: Borrowed ( self )
153
- }
154
- }
155
-
156
154
impl $crate:: meta:: ParamType for $T {
157
155
type Arg <' v> = $crate:: meta:: CowArg <' v, $T>;
158
156
@@ -199,7 +197,7 @@ macro_rules! declare_arg_method {
199
197
/// This is necessary for packed array dispatching to different "inner" backend signatures.
200
198
impl < T > AsArg < T > for CowArg < ' _ , T >
201
199
where
202
- for < ' r > T : ParamType < Arg < ' r > = CowArg < ' r , T > > + ' r ,
200
+ for < ' r > T : ToGodot ,
203
201
{
204
202
fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
205
203
where
@@ -273,7 +271,7 @@ impl AsArg<NodePath> for &String {
273
271
/// Implemented for all parameter types `T` that are allowed to receive [impl `AsArg<T>`][AsArg].
274
272
// ParamType used to be a subtrait of GodotType, but this can be too restrictive. For example, DynGd is not a "Godot canonical type"
275
273
// (GodotType), however it's still useful to store it in arrays -- which requires AsArg and subsequently ParamType.
276
- pub trait ParamType : sealed:: Sealed + Sized + ' static
274
+ pub trait ParamType : sealed:: Sealed + Sized + ' static + ToGodot
277
275
// GodotType bound not required right now, but conceptually should always be the case.
278
276
{
279
277
/// Canonical argument passing type, either `T` or an internally-used CoW type.
0 commit comments