Skip to content

Commit aa713bd

Browse files
committed
Internal ObjectArg<'gd> now has lifetime
1 parent 9da0f54 commit aa713bd

File tree

6 files changed

+27
-36
lines changed

6 files changed

+27
-36
lines changed

godot-core/src/meta/args/as_arg.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,7 @@ where
161161
where
162162
Self: 'arg,
163163
{
164-
// SAFETY: ObjectArg exists only during FFI call.
165-
let arg = unsafe { ObjectArg::from_gd(self) };
164+
let arg = ObjectArg::from_gd(self);
166165
CowArg::FfiObject(arg)
167166
}
168167
}
@@ -194,8 +193,7 @@ where
194193
where
195194
Self: 'arg,
196195
{
197-
// SAFETY: ObjectArg exists only during FFI call.
198-
let arg = unsafe { ObjectArg::from_gd(self) };
196+
let arg = ObjectArg::from_gd(self);
199197
CowArg::FfiObject(arg)
200198
}
201199
}
@@ -248,8 +246,7 @@ where
248246
where
249247
Self: 'arg,
250248
{
251-
// SAFETY: ObjectArg exists only during FFI call.
252-
let arg = unsafe { ObjectArg::from_option_gd(self) };
249+
let arg = ObjectArg::from_option_gd(self);
253250
CowArg::FfiObject(arg)
254251
}
255252
}
@@ -272,8 +269,7 @@ where
272269
where
273270
Self: 'arg,
274271
{
275-
// SAFETY: ObjectArg exists only during FFI call.
276-
let arg = unsafe { ObjectArg::from_gd(self) };
272+
let arg = ObjectArg::from_gd(self);
277273
CowArg::FfiObject(arg)
278274
}
279275
}
@@ -614,7 +610,7 @@ impl ArgPassing for ByObject {
614610
type Output<'r, T: 'r> = &'r T;
615611

616612
type FfiOutput<'f, T>
617-
= ObjectArg
613+
= ObjectArg<'f>
618614
where
619615
T: GodotType + 'f;
620616

@@ -627,13 +623,13 @@ impl ArgPassing for ByObject {
627623
value.to_godot().clone()
628624
}
629625

630-
fn ref_to_ffi<T>(value: &T) -> ObjectArg
626+
fn ref_to_ffi<T>(value: &T) -> ObjectArg<'_>
631627
where
632628
T: ToGodot<Pass = Self>,
633629
T::Via: GodotType,
634630
{
635631
let obj_ref: &T::Via = value.to_godot(); // implements GodotType.
636-
unsafe { obj_ref.as_object_arg() }
632+
obj_ref.as_object_arg()
637633
}
638634
}
639635

godot-core/src/meta/args/cow_arg.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub enum CowArg<'arg, T> {
2525
/// Raw object pointer for efficient FFI argument passing without cloning.
2626
///
2727
/// Only valid for object types (`Gd<T>`, `Option<Gd<T>>`). Can avoid the `Owned` creation.
28-
FfiObject(ObjectArg),
28+
FfiObject(ObjectArg<'arg>),
2929
}
3030

3131
impl<T> CowArg<'_, T> {
@@ -68,7 +68,7 @@ impl<T> CowArg<'_, T> {
6868
/// Extracts ObjectArg directly for ByObject FFI conversion.
6969
///
7070
/// Returns Some(ObjectArg) if this contains FfiObject, None otherwise.
71-
pub fn try_extract_object_arg(&self) -> Option<ObjectArg> {
71+
pub fn try_extract_object_arg(&self) -> Option<ObjectArg<'_>> {
7272
match self {
7373
CowArg::FfiObject(obj_arg) => Some(obj_arg.clone()),
7474
_ => None,

godot-core/src/meta/args/object_arg.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,23 @@ use crate::{obj, sys};
2121
/// without cloning. It supports nullable object passing for optional object arguments.
2222
#[derive(Debug, PartialEq)]
2323
#[doc(hidden)]
24-
pub struct ObjectArg {
24+
pub struct ObjectArg<'gd> {
2525
// Never dropped since it's just a view; see constructor.
2626
object_ptr: sys::GDExtensionObjectPtr,
27+
_lifetime: std::marker::PhantomData<&'gd ()>,
2728
}
2829

29-
impl ObjectArg {
30-
/// Creates `ObjectArg` from a `Gd`.
31-
///
32-
/// # Safety
33-
/// The referenced `Gd` must remain valid for the lifetime of this `ObjectArg`.
34-
pub unsafe fn from_gd<T: GodotClass>(obj: &Gd<T>) -> Self {
30+
impl<'gd> ObjectArg<'gd> {
31+
/// Creates a temporary `ObjectArg` from a `Gd` reference.
32+
pub fn from_gd<T: GodotClass>(obj: &'gd Gd<T>) -> Self {
3533
Self {
3634
object_ptr: obj.obj_sys(),
35+
_lifetime: std::marker::PhantomData,
3736
}
3837
}
3938

40-
/// Creates `ObjectArg` from an `Option<Gd>`.
41-
///
42-
/// # Safety
43-
/// The referenced `Gd`, if not `None`, must remain valid for the lifetime of this `ObjectArg`.
44-
pub unsafe fn from_option_gd<T: GodotClass>(obj: Option<&Gd<T>>) -> Self {
39+
/// Creates a temporary `ObjectArg` from an `Option<&Gd>` reference.
40+
pub fn from_option_gd<T: GodotClass>(obj: Option<&'gd Gd<T>>) -> Self {
4541
match obj {
4642
Some(gd) => Self::from_gd(gd),
4743
None => Self::null(),
@@ -52,6 +48,7 @@ impl ObjectArg {
5248
pub fn null() -> Self {
5349
Self {
5450
object_ptr: ptr::null_mut(),
51+
_lifetime: std::marker::PhantomData,
5552
}
5653
}
5754

@@ -67,16 +64,17 @@ impl ObjectArg {
6764
}
6865

6966
// #[derive(Clone)] doesn't seem to get bounds right.
70-
impl Clone for ObjectArg {
67+
impl<'gd> Clone for ObjectArg<'gd> {
7168
fn clone(&self) -> Self {
7269
Self {
7370
object_ptr: self.object_ptr,
71+
_lifetime: std::marker::PhantomData,
7472
}
7573
}
7674
}
7775

7876
// SAFETY: see impl GodotFfi for RawGd.
79-
unsafe impl GodotFfi for ObjectArg {
77+
unsafe impl<'gd> GodotFfi for ObjectArg<'gd> {
8078
// If anything changes here, keep in sync with RawGd impl.
8179

8280
const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::OBJECT);
@@ -117,7 +115,7 @@ unsafe impl GodotFfi for ObjectArg {
117115
}
118116
}
119117

120-
impl GodotFfiVariant for ObjectArg {
118+
impl<'gd> GodotFfiVariant for ObjectArg<'gd> {
121119
fn ffi_to_variant(&self) -> Variant {
122120
obj::object_ffi_to_variant(self)
123121
}
@@ -127,7 +125,7 @@ impl GodotFfiVariant for ObjectArg {
127125
}
128126
}
129127

130-
impl GodotNullableFfi for ObjectArg {
128+
impl<'gd> GodotNullableFfi for ObjectArg<'gd> {
131129
fn null() -> Self {
132130
Self::null()
133131
}

godot-core/src/meta/godot_convert/impls.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,9 @@ where
8686
}
8787

8888
// Only relevant for object types T.
89-
unsafe fn as_object_arg(&self) -> meta::ObjectArg {
89+
fn as_object_arg(&self) -> meta::ObjectArg<'_> {
9090
match self {
91-
Some(inner) => unsafe { inner.as_object_arg() },
91+
Some(inner) => inner.as_object_arg(),
9292
None => meta::ObjectArg::null(),
9393
}
9494
}

godot-core/src/meta/traits.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,8 @@ pub trait GodotType: GodotConvert<Via = Self> + sealed::Sealed + Sized + 'static
149149
/// # Panics
150150
/// If `Self` is not an object type (`Gd<T>`, `Option<Gd<T>>`). Note that `DynGd<T>` isn't directly implemented here, but uses `Gd<T>`'s
151151
/// impl on the FFI layer.
152-
///
153-
/// # Safety
154-
/// `self` must be kept alive while return value is in use. Might be addressed with lifetime in the future.
155152
#[doc(hidden)]
156-
unsafe fn as_object_arg(&self) -> crate::meta::ObjectArg {
153+
fn as_object_arg(&self) -> crate::meta::ObjectArg<'_> {
157154
panic!(
158155
"as_object_arg() called for non-object type: {}",
159156
std::any::type_name::<Self>()

godot-core/src/obj/gd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ impl<T: GodotClass> GodotType for Gd<T> {
961961
false
962962
}
963963

964-
unsafe fn as_object_arg(&self) -> meta::ObjectArg {
964+
fn as_object_arg(&self) -> meta::ObjectArg<'_> {
965965
meta::ObjectArg::from_gd(self)
966966
}
967967
}

0 commit comments

Comments
 (0)