Skip to content

Commit 00ba8c9

Browse files
authored
Merge pull request #409 from godot-rust/qol/traits
`Share` trait: deprecate + replace with `Clone`
2 parents 214f508 + 1b1cc44 commit 00ba8c9

File tree

19 files changed

+145
-125
lines changed

19 files changed

+145
-125
lines changed

examples/dodge-the-creeps/rust/src/main_scene.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ impl Main {
9191

9292
mob_scene.set_rotation(direction);
9393

94-
self.base.add_child(mob_scene.share().upcast());
94+
self.base.add_child(mob_scene.clone().upcast());
9595

9696
let mut mob = mob_scene.cast::<mob::Mob>();
9797
let range = {

godot-core/src/builtin/array.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ use sys::{ffi_methods, interface_fn, GodotFfi};
3434
/// Like in GDScript, `Array` acts as a reference type: multiple `Array` instances may
3535
/// refer to the same underlying array, and changes to one are visible in the other.
3636
///
37-
/// To create a copy that shares data with the original array, use [`Share::share()`]. If you want
38-
/// to create a copy of the data, use [`duplicate_shallow()`][Self::duplicate_shallow] or
39-
/// [`duplicate_deep()`][Self::duplicate_deep].
37+
/// To create a copy that shares data with the original array, use [`Clone::clone()`].
38+
/// If you want to create a copy of the data, use [`duplicate_shallow()`][Self::duplicate_shallow]
39+
/// or [`duplicate_deep()`][Self::duplicate_deep].
4040
///
4141
/// # Thread safety
4242
///
@@ -245,7 +245,7 @@ impl<T: VariantMetadata> Array<T> {
245245
/// (such as `Array`, `Dictionary` and `Object`) will still refer to the same value.
246246
///
247247
/// To create a deep copy, use [`duplicate_deep()`][Self::duplicate_deep] instead.
248-
/// To create a new reference to the same array data, use [`share()`][Share::share].
248+
/// To create a new reference to the same array data, use [`clone()`][Clone::clone].
249249
pub fn duplicate_shallow(&self) -> Self {
250250
let duplicate: VariantArray = self.as_inner().duplicate(false);
251251
// SAFETY: duplicate() returns a typed array with the same type as Self
@@ -257,7 +257,7 @@ impl<T: VariantMetadata> Array<T> {
257257
/// still be shallow copied.
258258
///
259259
/// To create a shallow copy, use [`duplicate_shallow()`][Self::duplicate_shallow] instead.
260-
/// To create a new reference to the same array data, use [`share()`][Share::share].
260+
/// To create a new reference to the same array data, use [`clone()`][Clone::clone].
261261
pub fn duplicate_deep(&self) -> Self {
262262
let duplicate: VariantArray = self.as_inner().duplicate(true);
263263
// SAFETY: duplicate() returns a typed array with the same type as Self
@@ -592,7 +592,7 @@ impl<T: VariantMetadata + ToVariant> Array<T> {
592592
//
593593
// - `from_arg_ptr`
594594
// Arrays are properly initialized through a `from_sys` call, but the ref-count should be incremented
595-
// as that is the callee's responsibility. Which we do by calling `std::mem::forget(array.share())`.
595+
// as that is the callee's responsibility. Which we do by calling `std::mem::forget(array.clone())`.
596596
unsafe impl<T: VariantMetadata> GodotFfi for Array<T> {
597597
ffi_methods! { type sys::GDExtensionTypePtr = *mut Opaque;
598598
fn from_sys;
@@ -609,7 +609,7 @@ unsafe impl<T: VariantMetadata> GodotFfi for Array<T> {
609609

610610
unsafe fn from_arg_ptr(ptr: sys::GDExtensionTypePtr, _call_type: sys::PtrcallType) -> Self {
611611
let array = Self::from_sys(ptr);
612-
std::mem::forget(array.share());
612+
std::mem::forget(array.clone());
613613
array
614614
}
615615
}
@@ -624,23 +624,31 @@ impl<T: VariantMetadata> fmt::Debug for Array<T> {
624624
/// Creates a new reference to the data in this array. Changes to the original array will be
625625
/// reflected in the copy and vice versa.
626626
///
627-
/// To create a (mostly) independent copy instead, see [`VariantArray::duplicate_shallow()`] and
628-
/// [`VariantArray::duplicate_deep()`].
629-
impl<T: VariantMetadata> Share for Array<T> {
630-
fn share(&self) -> Self {
627+
/// To create a (mostly) independent copy instead, see [`Array::duplicate_shallow()`] and
628+
/// [`Array::duplicate_deep()`].
629+
impl<T: VariantMetadata> Clone for Array<T> {
630+
fn clone(&self) -> Self {
631+
// SAFETY: `self` is a valid array, since we have a reference that keeps it alive.
631632
let array = unsafe {
632633
Self::from_sys_init(|self_ptr| {
633634
let ctor = ::godot_ffi::builtin_fn!(array_construct_copy);
634635
let args = [self.sys_const()];
635636
ctor(self_ptr, args.as_ptr());
636637
})
637638
};
639+
638640
array
639641
.with_checked_type()
640642
.expect("copied array should have same type as original array")
641643
}
642644
}
643645

646+
impl<T: VariantMetadata> Share for Array<T> {
647+
fn share(&self) -> Self {
648+
self.clone()
649+
}
650+
}
651+
644652
impl<T: VariantMetadata + TypeStringHint> TypeStringHint for Array<T> {
645653
fn type_string() -> String {
646654
format!("{}:{}", VariantType::Array as i32, T::type_string())
@@ -651,7 +659,7 @@ impl<T: VariantMetadata> Property for Array<T> {
651659
type Intermediate = Self;
652660

653661
fn get_property(&self) -> Self::Intermediate {
654-
self.share()
662+
self.clone()
655663
}
656664

657665
fn set_property(&mut self, value: Self::Intermediate) {

godot-core/src/builtin/dictionary.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ impl Dictionary {
4949
/// will not be shared with the original dictionary. Note that any `Object`-derived elements will
5050
/// still be shallow copied.
5151
///
52-
/// To create a shallow copy, use [`Self::duplicate_shallow`] instead. To create a new reference to
53-
/// the same array data, use [`Share::share`].
52+
/// To create a shallow copy, use [`Self::duplicate_shallow()`] instead.
53+
/// To create a new reference to the same dictionary data, use [`clone()`][Clone::clone].
5454
///
5555
/// _Godot equivalent: `dict.duplicate(true)`_
5656
pub fn duplicate_deep(&self) -> Self {
@@ -61,8 +61,8 @@ impl Dictionary {
6161
/// any reference types (such as `Array`, `Dictionary` and `Object`) will still refer to the
6262
/// same value.
6363
///
64-
/// To create a deep copy, use [`Self::duplicate_deep`] instead. To create a new reference to the
65-
/// same dictionary data, use [`Share::share`].
64+
/// To create a deep copy, use [`Self::duplicate_deep()`] instead.
65+
/// To create a new reference to the same dictionary data, use [`clone()`][Clone::clone].
6666
///
6767
/// _Godot equivalent: `dict.duplicate(false)`_
6868
pub fn duplicate_shallow(&self) -> Self {
@@ -263,7 +263,7 @@ impl Dictionary {
263263
// - `from_arg_ptr`
264264
// Dictionaries are properly initialized through a `from_sys` call, but the ref-count should be
265265
// incremented as that is the callee's responsibility. Which we do by calling
266-
// `std::mem::forget(dictionary.share())`.
266+
// `std::mem::forget(dictionary.clone())`.
267267
unsafe impl GodotFfi for Dictionary {
268268
ffi_methods! { type sys::GDExtensionTypePtr = *mut Opaque;
269269
fn from_sys;
@@ -280,7 +280,7 @@ unsafe impl GodotFfi for Dictionary {
280280

281281
unsafe fn from_arg_ptr(ptr: sys::GDExtensionTypePtr, _call_type: sys::PtrcallType) -> Self {
282282
let dictionary = Self::from_sys(ptr);
283-
std::mem::forget(dictionary.share());
283+
std::mem::forget(dictionary.clone());
284284
dictionary
285285
}
286286
}
@@ -304,8 +304,9 @@ impl fmt::Debug for Dictionary {
304304
///
305305
/// To create a (mostly) independent copy instead, see [`Dictionary::duplicate_shallow()`] and
306306
/// [`Dictionary::duplicate_deep()`].
307-
impl Share for Dictionary {
308-
fn share(&self) -> Self {
307+
impl Clone for Dictionary {
308+
fn clone(&self) -> Self {
309+
// SAFETY: `self` is a valid dictionary, since we have a reference that keeps it alive.
309310
unsafe {
310311
Self::from_sys_init(|self_ptr| {
311312
let ctor = sys::builtin_fn!(dictionary_construct_copy);
@@ -316,11 +317,17 @@ impl Share for Dictionary {
316317
}
317318
}
318319

320+
impl Share for Dictionary {
321+
fn share(&self) -> Self {
322+
self.clone()
323+
}
324+
}
325+
319326
impl Property for Dictionary {
320327
type Intermediate = Self;
321328

322329
fn get_property(&self) -> Self::Intermediate {
323-
self.share()
330+
self.clone()
324331
}
325332

326333
fn set_property(&mut self, value: Self::Intermediate) {

godot-core/src/builtin/string/godot_string.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl GodotString {
108108
// - `from_arg_ptr`
109109
// Strings are properly initialized through a `from_sys` call, but the ref-count should be
110110
// incremented as that is the callee's responsibility. Which we do by calling
111-
// `std::mem::forget(string.share())`.
111+
// `std::mem::forget(string.clone())`.
112112
unsafe impl GodotFfi for GodotString {
113113
ffi_methods! { type sys::GDExtensionTypePtr = *mut Opaque;
114114
fn from_sys;

godot-core/src/builtin/string/node_path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl NodePath {
4646
// - `from_arg_ptr`
4747
// NodePaths are properly initialized through a `from_sys` call, but the ref-count should be
4848
// incremented as that is the callee's responsibility. Which we do by calling
49-
// `std::mem::forget(node_path.share())`.
49+
// `std::mem::forget(node_path.clone())`.
5050
unsafe impl GodotFfi for NodePath {
5151
ffi_methods! { type sys::GDExtensionTypePtr = *mut Opaque;
5252
fn from_sys;

godot-core/src/builtin/string/string_name.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl StringName {
7373
// - `from_arg_ptr`
7474
// StringNames are properly initialized through a `from_sys` call, but the ref-count should be
7575
// incremented as that is the callee's responsibility. Which we do by calling
76-
// `std::mem::forget(string_name.share())`.
76+
// `std::mem::forget(string_name.clone())`.
7777
unsafe impl GodotFfi for StringName {
7878
ffi_methods! { type sys::GDExtensionTypePtr = *mut Opaque;
7979
fn from_sys;

godot-core/src/engine.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,8 @@ where
112112
// This would need more sophisticated upcast design, e.g. T::upcast_{ref|mut}::<U>() for indirect relations
113113
// to make the indirect Deref more explicit
114114

115-
use crate::obj::Share;
116-
117115
let path = path.into();
118-
let node = self.share().upcast::<Node>();
116+
let node = self.clone().upcast::<Node>();
119117

120118
<Node as NodeExt>::try_get_node_as(&*node, path)
121119
}

godot-core/src/obj/gd.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use crate::{callbacks, engine, out};
3939
/// In particular, the memory management strategy is fully dependent on `T`:
4040
///
4141
/// * Objects of type [`RefCounted`] or inherited from it are **reference-counted**. This means that every time a smart pointer is
42-
/// shared using [`Share::share()`], the reference counter is incremented, and every time one is dropped, it is decremented.
42+
/// shared using [`Clone::clone()`], the reference counter is incremented, and every time one is dropped, it is decremented.
4343
/// This ensures that the last reference (either in Rust or Godot) will deallocate the object and call `T`'s destructor.
4444
///
4545
/// * Objects inheriting from [`Object`] which are not `RefCounted` (or inherited) are **manually-managed**.
@@ -309,7 +309,7 @@ impl<T: GodotClass> Gd<T> {
309309
/// struct MyClass {}
310310
///
311311
/// let obj: Gd<MyClass> = Gd::new_default();
312-
/// let base = obj.share().upcast::<Node>();
312+
/// let base = obj.clone().upcast::<Node>();
313313
/// ```
314314
pub fn upcast<Base>(self) -> Gd<Base>
315315
where
@@ -462,7 +462,7 @@ impl<T: GodotClass> Gd<T> {
462462

463463
/// Returns a callable referencing a method from this object named `method_name`.
464464
pub fn callable<S: Into<StringName>>(&self, method_name: S) -> Callable {
465-
Callable::from_object_method(self.share(), method_name)
465+
Callable::from_object_method(self.clone(), method_name)
466466
}
467467
}
468468

@@ -590,7 +590,7 @@ where
590590
if T::Mem::pass_as_ref(call_type) {
591591
interface_fn!(ref_set_object)(ptr as sys::GDExtensionRefPtr, self.obj_sys())
592592
} else {
593-
std::ptr::write(ptr as *mut _, self.opaque)
593+
ptr::write(ptr as *mut _, self.opaque)
594594
}
595595
// We've passed ownership to caller.
596596
std::mem::forget(self);
@@ -709,10 +709,16 @@ impl<T: GodotClass> Drop for Gd<T> {
709709
}
710710
}
711711

712+
impl<T: GodotClass> Clone for Gd<T> {
713+
fn clone(&self) -> Self {
714+
out!("Gd::clone");
715+
Self::from_opaque(self.opaque).with_inc_refcount()
716+
}
717+
}
718+
712719
impl<T: GodotClass> Share for Gd<T> {
713720
fn share(&self) -> Self {
714-
out!("Gd::share");
715-
Self::from_opaque(self.opaque).with_inc_refcount()
721+
self.clone()
716722
}
717723
}
718724

@@ -739,7 +745,7 @@ impl<T: GodotClass> Property for Gd<T> {
739745
type Intermediate = Self;
740746

741747
fn get_property(&self) -> Self {
742-
self.share()
748+
self.clone()
743749
}
744750

745751
fn set_property(&mut self, value: Self) {

godot-core/src/obj/traits.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ pub trait Share {
7171
/// Creates a new reference that points to the same object.
7272
///
7373
/// If the referred-to object is reference-counted, this will increment the count.
74+
#[deprecated = "Replaced with `Clone::clone()`."]
7475
fn share(&self) -> Self;
7576
}
7677

godot/src/lib.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@
1212
//!
1313
//! Godot is written in C++, which doesn't have the same strict guarantees about safety and
1414
//! mutability that Rust does. As a result, not everything in this crate will look and feel
15-
//! entirely "rusty". We distinguish four different kinds of types:
15+
//! entirely "rusty".
16+
//!
17+
//! Traits such as `Clone`, `PartialEq` or `PartialOrd` are designed to mirror Godot semantics,
18+
//! except in cases where Rust is stricter (e.g. float ordering). Cloning a type results in the
19+
//! same observable behavior as assignment or parameter-passing of a GDScript variable.
20+
//!
21+
//! We distinguish four different kinds of types:
1622
//!
1723
//! 1. **Value types**: `i64`, `f64`, and mathematical types like
1824
//! [`Vector2`][crate::builtin::Vector2] and [`Color`][crate::builtin::Color].
@@ -43,11 +49,9 @@
4349
//! careful when using such types. For example, when iterating over an `Array`, make sure that
4450
//! it isn't being modified at the same time through another reference.
4551
//!
46-
//! To avoid confusion these types don't implement `Clone`. You can use
47-
//! [`Share`][crate::obj::Share] to create a new reference to the same instance, and
48-
//! type-specific methods such as
49-
//! [`Array::duplicate_deep()`][crate::builtin::Array::duplicate_deep] to make actual
50-
//! copies. <br><br>
52+
//! `Clone::clone()` on these types creates a new reference to the same instance, while
53+
//! type-specific methods such as [`Array::duplicate_deep()`][crate::builtin::Array::duplicate_deep]
54+
//! can be used to make actual copies. <br><br>
5155
//!
5256
//! 4. **Manually managed types**: [`Gd<T>`][crate::obj::Gd] where `T` inherits from
5357
//! [`Object`][crate::engine::Object] but not from [`RefCounted`][crate::engine::RefCounted];

itest/rust/src/builtin_tests/containers/array_test.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn array_hash() {
9999
#[itest]
100100
fn array_share() {
101101
let mut array = array![1, 2];
102-
let shared = array.share();
102+
let shared = array.clone();
103103
array.set(0, 3);
104104
assert_eq!(shared.get(0), 3);
105105
}
@@ -372,7 +372,7 @@ fn untyped_array_return_from_godot_func() {
372372
let mut node = Node::new_alloc();
373373
let mut child = Node::new_alloc();
374374
child.set_name("child_node".into());
375-
node.add_child(child.share());
375+
node.add_child(child.clone());
376376
node.queue_free(); // Do not leak even if the test fails.
377377
let result = node.get_node_and_resource("child_node".into());
378378

@@ -409,7 +409,7 @@ fn typed_array_return_from_godot_func() {
409409
let mut node = Node::new_alloc();
410410
let mut child = Node::new_alloc();
411411
child.set_name("child_node".into());
412-
node.add_child(child.share());
412+
node.add_child(child.clone());
413413
node.queue_free(); // Do not leak even if the test fails.
414414
let children = node.get_children();
415415

@@ -419,7 +419,7 @@ fn typed_array_return_from_godot_func() {
419419
#[itest]
420420
fn typed_array_try_from_untyped() {
421421
let node = Node::new_alloc();
422-
let array = VariantArray::from(&[node.share().to_variant()]);
422+
let array = VariantArray::from(&[node.clone().to_variant()]);
423423
assert_eq!(
424424
array.to_variant().try_to::<Array<Option<Gd<Node>>>>(),
425425
Err(VariantConversionError::BadType)
@@ -430,7 +430,7 @@ fn typed_array_try_from_untyped() {
430430
#[itest]
431431
fn untyped_array_try_from_typed() {
432432
let node = Node::new_alloc();
433-
let array = Array::<Option<Gd<Node>>>::from(&[Some(node.share())]);
433+
let array = Array::<Option<Gd<Node>>>::from(&[Some(node.clone())]);
434434
assert_eq!(
435435
array.to_variant().try_to::<VariantArray>(),
436436
Err(VariantConversionError::BadType)

itest/rust/src/builtin_tests/containers/callable_test.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use godot::bind::{godot_api, GodotClass};
88
use godot::builtin::inner::InnerCallable;
99
use godot::builtin::{varray, Callable, GodotString, StringName, ToVariant, Variant};
1010
use godot::engine::{Node2D, Object};
11-
use godot::obj::{Gd, Share};
11+
use godot::obj::Gd;
1212

1313
use crate::framework::itest;
1414

@@ -66,7 +66,7 @@ fn callable_object_method() {
6666
let obj = Gd::<CallableTestObj>::new_default();
6767
let callable = obj.callable("foo");
6868

69-
assert_eq!(callable.object(), Some(obj.share().upcast::<Object>()));
69+
assert_eq!(callable.object(), Some(obj.clone().upcast::<Object>()));
7070
assert_eq!(callable.object_id(), Some(obj.instance_id()));
7171
assert_eq!(callable.method_name(), Some("foo".into()));
7272

@@ -109,7 +109,7 @@ fn callable_call_return() {
109109
#[itest]
110110
fn callable_call_engine() {
111111
let obj = Node2D::new_alloc();
112-
let cb = Callable::from_object_method(obj.share(), "set_position");
112+
let cb = Callable::from_object_method(obj.clone(), "set_position");
113113
let inner: InnerCallable = cb.as_inner();
114114

115115
assert!(!inner.is_null());

0 commit comments

Comments
 (0)