@@ -91,18 +91,29 @@ where
91
91
// ergonomics out weigh the runtime cost. Using the CowArg allows us to create a blanket implementation of the trait for all types that
92
92
// implement ToGodot.
93
93
#[ doc( hidden) ]
94
- fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
94
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , T >
95
95
where
96
- Self : ' r ;
96
+ Self : ' arg ;
97
+
98
+ /// FFI-optimized argument conversion that may use `FfiObject` when beneficial.
99
+ ///
100
+ /// Defaults to calling `into_arg()`, which always works, but might be an `Owned` for a conservative approach (e.g. object upcast).
101
+ #[ doc( hidden) ]
102
+ fn into_ffi_arg < ' arg > ( self ) -> CowArg < ' arg , T >
103
+ where
104
+ Self : ' arg ,
105
+ {
106
+ self . into_arg ( )
107
+ }
97
108
}
98
109
99
110
impl < T > AsArg < T > for & T
100
111
where
101
112
T : ToGodot < Pass = ByRef > ,
102
113
{
103
- fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
114
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , T >
104
115
where
105
- Self : ' r ,
116
+ Self : ' arg ,
106
117
{
107
118
CowArg :: Borrowed ( self )
108
119
}
@@ -112,9 +123,9 @@ impl<T> AsArg<T> for T
112
123
where
113
124
T : ToGodot < Pass = ByValue > ,
114
125
{
115
- fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
126
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , T >
116
127
where
117
- Self : ' r ,
128
+ Self : ' arg ,
118
129
{
119
130
CowArg :: Owned ( self )
120
131
}
@@ -125,98 +136,169 @@ where
125
136
126
137
// TODO(v0.4): all objects + optional objects should be pass-by-ref.
127
138
139
+ // Convert `Gd` -> `Gd` (with upcast).
128
140
impl < T , Base > AsArg < Gd < Base > > for & Gd < T >
129
141
where
130
142
T : Inherits < Base > ,
131
143
Base : GodotClass ,
132
144
{
133
- fn into_arg < ' r > ( self ) -> CowArg < ' r , Gd < Base > >
145
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , Gd < Base > >
134
146
where
135
- Self : ' r ,
147
+ Self : ' arg ,
136
148
{
137
- CowArg :: Owned ( self . clone ( ) . upcast :: < Base > ( ) )
149
+ if T :: IS_SAME_CLASS {
150
+ // SAFETY: T == Base, so &Gd<T> can be treated as &Gd<Base>.
151
+ let gd_ref = unsafe { std:: mem:: transmute :: < & Gd < T > , & Gd < Base > > ( self ) } ;
152
+ CowArg :: Borrowed ( gd_ref)
153
+ } else {
154
+ // Different types: clone and upcast. May incur ref-count increment for RefCounted objects, but the common path
155
+ // of FFI passing is already optimized.
156
+ CowArg :: Owned ( self . clone ( ) . upcast ( ) )
157
+ }
158
+ }
159
+
160
+ fn into_ffi_arg < ' arg > ( self ) -> CowArg < ' arg , Gd < Base > >
161
+ where
162
+ Self : ' arg ,
163
+ {
164
+ // SAFETY: ObjectArg exists only during FFI call.
165
+ let arg = unsafe { ObjectArg :: from_gd ( self ) } ;
166
+ CowArg :: FfiObject ( arg)
138
167
}
139
168
}
140
169
141
- impl < T , U , D > AsArg < DynGd < T , D > > for & DynGd < U , D >
170
+ /// Convert `DynGd` -> `DynGd` (with upcast).
171
+ impl < T , D , Base > AsArg < DynGd < Base , D > > for & DynGd < T , D >
142
172
where
143
- T : GodotClass ,
144
- U : Inherits < T > ,
173
+ T : Inherits < Base > ,
145
174
D : ?Sized ,
175
+ Base : GodotClass ,
146
176
{
147
- fn into_arg < ' r > ( self ) -> CowArg < ' r , DynGd < T , D > >
177
+ //noinspection RsConstantConditionIf - false positive in IDE for `T::IS_SAME_CLASS`.
178
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , DynGd < Base , D > >
148
179
where
149
- Self : ' r ,
180
+ Self : ' arg ,
150
181
{
151
- CowArg :: Owned ( self . clone ( ) . upcast :: < T > ( ) )
182
+ if T :: IS_SAME_CLASS {
183
+ // SAFETY: T == Base, so &DynGd<T, D> can be treated as &DynGd<Base, D>.
184
+ let gd_ref = unsafe { std:: mem:: transmute :: < & Gd < T > , & DynGd < Base , D > > ( self ) } ;
185
+ CowArg :: Borrowed ( gd_ref)
186
+ } else {
187
+ // Different types: clone and upcast. May incur ref-count increment for RefCounted objects, but the common path
188
+ // of FFI passing is already optimized.
189
+ CowArg :: Owned ( self . clone ( ) . upcast ( ) )
190
+ }
191
+ }
192
+
193
+ fn into_ffi_arg < ' arg > ( self ) -> CowArg < ' arg , DynGd < Base , D > >
194
+ where
195
+ Self : ' arg ,
196
+ {
197
+ // SAFETY: ObjectArg exists only during FFI call.
198
+ let arg = unsafe { ObjectArg :: from_gd ( self ) } ;
199
+ CowArg :: FfiObject ( arg)
152
200
}
153
201
}
154
202
155
- // Convert DynGd -> Gd (with upcast).
156
- impl < ' r , T , U , D > AsArg < Gd < T > > for & ' r DynGd < U , D >
203
+ // Convert ` DynGd` -> `Gd` (with upcast).
204
+ impl < T , D , Base > AsArg < Gd < Base > > for & DynGd < T , D >
157
205
where
158
- T : GodotClass ,
159
- U : Inherits < T > ,
206
+ T : Inherits < Base > ,
160
207
D : ?Sized ,
208
+ Base : GodotClass ,
161
209
{
162
- fn into_arg < ' cow > ( self ) -> CowArg < ' cow , Gd < T > >
210
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , Gd < Base > >
211
+ where
212
+ Self : ' arg ,
213
+ {
214
+ let gd_ref: & Gd < T > = self ; // DynGd -> Gd deref.
215
+ AsArg :: into_arg ( gd_ref)
216
+ }
217
+
218
+ fn into_ffi_arg < ' arg > ( self ) -> CowArg < ' arg , Gd < Base > >
163
219
where
164
- ' r : ' cow ,
220
+ Self : ' arg ,
165
221
{
166
- CowArg :: Owned ( self . clone ( ) . upcast :: < T > ( ) . into_gd ( ) )
222
+ let gd_ref: & Gd < T > = self ; // DynGd -> Gd deref.
223
+ AsArg :: into_ffi_arg ( gd_ref)
167
224
}
168
225
}
169
226
170
227
// ----------------------------------------------------------------------------------------------------------------------------------------------
171
228
// Optional object (Gd + DynGd) impls
172
229
173
- impl < T , U > AsArg < Option < Gd < T > > > for & Option < Gd < U > >
230
+ /// Convert `Option<&Gd>` -> `Option<Gd>` (with upcast).
231
+ impl < T , Base > AsArg < Option < Gd < Base > > > for Option < & Gd < T > >
174
232
where
175
- T : GodotClass + Bounds < Declarer = bounds :: DeclEngine > ,
176
- U : Inherits < T > ,
233
+ T : Inherits < Base > ,
234
+ Base : GodotClass + Bounds < Declarer = bounds :: DeclEngine > ,
177
235
{
178
- fn into_arg < ' r > ( self ) -> CowArg < ' r , Option < Gd < T > > > {
236
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , Option < Gd < Base > > >
237
+ where
238
+ Self : ' arg ,
239
+ {
240
+ // Upcasting to an owned value Gd<Base> requires cloning. Optimized path in into_ffi_arg().
179
241
match self {
180
- Some ( gd ) => CowArg :: Owned ( Some ( gd . clone ( ) . upcast :: < T > ( ) ) ) ,
242
+ Some ( gd_ref ) => AsArg :: into_arg ( gd_ref ) ,
181
243
None => CowArg :: Owned ( None ) ,
182
244
}
183
245
}
184
- }
185
246
186
- impl < T , U > AsArg < Option < Gd < T > > > for Option < & Gd < U > >
187
- where
188
- T : GodotClass + Bounds < Declarer = bounds:: DeclEngine > ,
189
- U : Inherits < T > ,
190
- {
191
- fn into_arg < ' cow > ( self ) -> CowArg < ' cow , Option < Gd < T > > > {
192
- // This needs to construct a new Option<Gd<T>>, so cloning is unavoidable
193
- // since we go from Option<&Gd<U>> to Option<Gd<T>>
194
- match self {
195
- Some ( gd) => CowArg :: Owned ( Some ( gd. clone ( ) . upcast :: < T > ( ) ) ) ,
196
- None => CowArg :: Owned ( None ) ,
197
- }
247
+ fn into_ffi_arg < ' arg > ( self ) -> CowArg < ' arg , Option < Gd < Base > > >
248
+ where
249
+ Self : ' arg ,
250
+ {
251
+ // SAFETY: ObjectArg exists only during FFI call.
252
+ let arg = unsafe { ObjectArg :: from_option_gd ( self ) } ;
253
+ CowArg :: FfiObject ( arg)
198
254
}
199
255
}
200
256
201
- impl < T , U > AsArg < Option < Gd < T > > > for & Gd < U >
257
+ /// Convert `&Gd` -> `Option<Gd>` (with upcast).
258
+ impl < T , Base > AsArg < Option < Gd < Base > > > for & Gd < T >
202
259
where
203
- T : GodotClass + Bounds < Declarer = bounds :: DeclEngine > ,
204
- U : Inherits < T > ,
260
+ T : Inherits < Base > ,
261
+ Base : GodotClass + Bounds < Declarer = bounds :: DeclEngine > ,
205
262
{
206
- fn into_arg < ' cow > ( self ) -> CowArg < ' cow , Option < Gd < T > > > {
207
- CowArg :: Owned ( Some ( self . clone ( ) . upcast :: < T > ( ) ) )
263
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , Option < Gd < Base > > >
264
+ where
265
+ Self : ' arg ,
266
+ {
267
+ // Upcasting to an owned value Gd<Base> requires cloning. Optimized path in into_ffi_arg().
268
+ CowArg :: Owned ( Some ( self . clone ( ) . upcast :: < Base > ( ) ) )
269
+ }
270
+
271
+ fn into_ffi_arg < ' arg > ( self ) -> CowArg < ' arg , Option < Gd < Base > > >
272
+ where
273
+ Self : ' arg ,
274
+ {
275
+ // SAFETY: ObjectArg exists only during FFI call.
276
+ let arg = unsafe { ObjectArg :: from_gd ( self ) } ;
277
+ CowArg :: FfiObject ( arg)
208
278
}
209
279
}
210
280
211
- impl < T , U , D > AsArg < Option < Gd < T > > > for & DynGd < U , D >
281
+ /// Convert `&DynGd` -> `Option<Gd>` (with upcast).
282
+ impl < T , D , Base > AsArg < Option < Gd < Base > > > for & DynGd < T , D >
212
283
where
213
- T : GodotClass + Bounds < Declarer = bounds:: DeclEngine > ,
214
- U : Inherits < T > ,
284
+ T : Inherits < Base > ,
215
285
D : ?Sized ,
286
+ Base : GodotClass + Bounds < Declarer = bounds:: DeclEngine > ,
216
287
{
217
- fn into_arg < ' cow > ( self ) -> CowArg < ' cow , Option < Gd < T > > > {
218
- let gd: & Gd < U > = self ; // Deref
219
- CowArg :: Owned ( Some ( gd. clone ( ) . upcast :: < T > ( ) ) )
288
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , Option < Gd < Base > > >
289
+ where
290
+ Self : ' arg ,
291
+ {
292
+ let gd_ref: & Gd < T > = self ; // DynGd -> Gd deref.
293
+ AsArg :: into_arg ( gd_ref)
294
+ }
295
+
296
+ fn into_ffi_arg < ' arg > ( self ) -> CowArg < ' arg , Option < Gd < Base > > >
297
+ where
298
+ Self : ' arg ,
299
+ {
300
+ let gd_ref: & Gd < T > = self ; // DynGd -> Gd deref.
301
+ AsArg :: into_ffi_arg ( gd_ref)
220
302
}
221
303
}
222
304
@@ -251,9 +333,9 @@ where
251
333
/// }
252
334
/// }
253
335
/// ```
254
- pub fn owned_into_arg < ' r , T > ( owned_val : T ) -> impl AsArg < T > + ' r
336
+ pub fn owned_into_arg < ' arg , T > ( owned_val : T ) -> impl AsArg < T > + ' arg
255
337
where
256
- T : ToGodot + ' r ,
338
+ T : ToGodot + ' arg ,
257
339
{
258
340
CowArg :: Owned ( owned_val)
259
341
}
@@ -354,9 +436,9 @@ impl<T> AsArg<T> for CowArg<'_, T>
354
436
where
355
437
for < ' r > T : ToGodot ,
356
438
{
357
- fn into_arg < ' r > ( self ) -> CowArg < ' r , T >
439
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , T >
358
440
where
359
- Self : ' r ,
441
+ Self : ' arg ,
360
442
{
361
443
self
362
444
}
@@ -368,13 +450,13 @@ where
368
450
// Note: for all string types S, `impl AsArg<S> for &mut String` is not yet provided, but we can add them if needed.
369
451
370
452
impl AsArg < GString > for & str {
371
- fn into_arg < ' r > ( self ) -> CowArg < ' r , GString > {
453
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , GString > {
372
454
CowArg :: Owned ( GString :: from ( self ) )
373
455
}
374
456
}
375
457
376
458
impl AsArg < GString > for & String {
377
- fn into_arg < ' r > ( self ) -> CowArg < ' r , GString > {
459
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , GString > {
378
460
CowArg :: Owned ( GString :: from ( self ) )
379
461
}
380
462
}
@@ -383,19 +465,19 @@ impl AsArg<GString> for &String {
383
465
// StringName
384
466
385
467
impl AsArg < StringName > for & str {
386
- fn into_arg < ' r > ( self ) -> CowArg < ' r , StringName > {
468
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , StringName > {
387
469
CowArg :: Owned ( StringName :: from ( self ) )
388
470
}
389
471
}
390
472
391
473
impl AsArg < StringName > for & String {
392
- fn into_arg < ' r > ( self ) -> CowArg < ' r , StringName > {
474
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , StringName > {
393
475
CowArg :: Owned ( StringName :: from ( self ) )
394
476
}
395
477
}
396
478
397
479
impl AsArg < StringName > for & ' static CStr {
398
- fn into_arg < ' r > ( self ) -> CowArg < ' r , StringName > {
480
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , StringName > {
399
481
CowArg :: Owned ( StringName :: from ( self ) )
400
482
}
401
483
}
@@ -404,13 +486,13 @@ impl AsArg<StringName> for &'static CStr {
404
486
// NodePath
405
487
406
488
impl AsArg < NodePath > for & str {
407
- fn into_arg < ' r > ( self ) -> CowArg < ' r , NodePath > {
489
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , NodePath > {
408
490
CowArg :: Owned ( NodePath :: from ( self ) )
409
491
}
410
492
}
411
493
412
494
impl AsArg < NodePath > for & String {
413
- fn into_arg < ' r > ( self ) -> CowArg < ' r , NodePath > {
495
+ fn into_arg < ' arg > ( self ) -> CowArg < ' arg , NodePath > {
414
496
CowArg :: Owned ( NodePath :: from ( self ) )
415
497
}
416
498
}
0 commit comments