Skip to content

Commit

Permalink
Remove impl AsObjectArg<T> for Gd<T> values
Browse files Browse the repository at this point in the history
  • Loading branch information
Bromeon committed Nov 9, 2024
1 parent 2a5f011 commit d2c61db
Show file tree
Hide file tree
Showing 10 changed files with 33 additions and 20 deletions.
11 changes: 10 additions & 1 deletion godot-core/src/obj/object_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ use std::ptr;
/// </div>

#[diagnostic::on_unimplemented(
message = "The provided argument of type `{Self}` cannot be converted to a `Gd<{T}>` parameter"
message = "Argument of type `{Self}` cannot be passed to an `impl AsObjectArg<{T}>` parameter",
note = "If you pass by value, consider borrowing instead.",
note = "See also `AsObjectArg` docs: https://godot-rust.github.io/docs/gdext/master/godot/meta/trait.AsObjectArg.html"
)]
pub trait AsObjectArg<T>
where
Expand All @@ -41,6 +43,12 @@ where
fn consume_arg(self) -> ObjectCow<T>;
}

/*
Currently not implemented for values, to be consistent with AsArg for by-ref builtins. The idea is that this can discover patterns like
api.method(refc.clone()), and encourage better performance with api.method(&refc). However, we need to see if there's a notable ergonomic
impact, and consider that for nodes, Gd<T> copies are relatively cheap (no ref-counting). There is also some value in prematurely ending
the lifetime of a Gd<T> by moving out, so it's not accidentally used later.
impl<T, U> AsObjectArg<T> for Gd<U>
where
T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
Expand All @@ -54,6 +62,7 @@ where
ObjectCow::Owned(self.upcast())
}
}
*/

impl<T, U> AsObjectArg<T> for &Gd<U>
where
Expand Down
2 changes: 1 addition & 1 deletion godot-core/src/obj/script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ impl<'a, T: ScriptInstance> SiMut<'a, T> {
/// let name = this.base().get_name();
/// godot_print!("name is {name}");
/// // However, we cannot call methods that require `&mut Base`, such as:
/// // this.base().add_child(node);
/// // this.base().add_child(&node);
/// Ok(Variant::nil())
/// }
/// # fn class_name(&self) -> GString { todo!() }
Expand Down
4 changes: 2 additions & 2 deletions godot-core/src/obj/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ pub trait WithBaseField: GodotClass + Bounds<Declarer = bounds::DeclUser> {
/// fn process(&mut self, _delta: f64) {
/// let node = Node::new_alloc();
/// // fails because `add_child` requires a mutable reference.
/// self.base().add_child(node);
/// self.base().add_child(&node);
/// }
/// }
///
Expand Down Expand Up @@ -344,7 +344,7 @@ pub trait WithBaseField: GodotClass + Bounds<Declarer = bounds::DeclUser> {
/// impl INode for MyClass {
/// fn process(&mut self, _delta: f64) {
/// let node = Node::new_alloc();
/// self.base_mut().add_child(node);
/// self.base_mut().add_child(&node);
/// }
/// }
///
Expand Down
6 changes: 3 additions & 3 deletions itest/rust/src/engine_tests/node_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ fn node_get_node() {

let mut parent = Node3D::new_alloc();
parent.set_name("parent");
parent.add_child(child);
parent.add_child(&child);

let mut grandparent = Node::new_alloc();
grandparent.set_name("grandparent");
grandparent.add_child(parent);
grandparent.add_child(&parent);

// Directly on Gd<T>
let found = grandparent.get_node_as::<Node3D>("parent/child");
Expand Down Expand Up @@ -74,7 +74,7 @@ fn node_scene_tree() {
assert_eq!(err, global::Error::OK);

let mut tree = SceneTree::new_alloc();
let err = tree.change_scene_to_packed(scene);
let err = tree.change_scene_to_packed(&scene);
assert_eq!(err, global::Error::OK);

// Note: parent + child are not owned by PackedScene, thus need to be freed
Expand Down
16 changes: 10 additions & 6 deletions itest/rust/src/object_tests/object_arg_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use godot::obj::{Gd, NewAlloc, NewGd};
use crate::framework::itest;
use crate::object_tests::object_test::{user_refc_instance, RefcPayload};

/*
#[itest]
fn object_arg_owned() {
with_objects(|manual, refc| {
Expand All @@ -22,6 +23,7 @@ fn object_arg_owned() {
(a, b)
});
}
*/

#[itest]
fn object_arg_borrowed() {
Expand All @@ -43,6 +45,7 @@ fn object_arg_borrowed_mut() {
});
}

/*
#[itest]
fn object_arg_option_owned() {
with_objects(|manual, refc| {
Expand All @@ -52,6 +55,7 @@ fn object_arg_option_owned() {
(a, b)
});
}
*/

#[itest]
fn object_arg_option_borrowed() {
Expand Down Expand Up @@ -80,10 +84,10 @@ fn object_arg_option_none() {

// Will emit errors but should not crash.
let db = ClassDb::singleton();
let error = db.class_set_property(manual, "name", &Variant::from("hello"));
let error = db.class_set_property(&manual, "name", &Variant::from("hello"));
assert_eq!(error, global::Error::ERR_UNAVAILABLE);

let error = db.class_set_property(refc, "value", &Variant::from(-123));
let error = db.class_set_property(&refc, "value", &Variant::from(-123));
assert_eq!(error, global::Error::ERR_UNAVAILABLE);
}

Expand All @@ -106,14 +110,14 @@ fn object_arg_owned_default_params() {
let b = ResourceFormatLoader::new_gd();

// Use direct and explicit _ex() call syntax.
ResourceLoader::singleton().add_resource_format_loader(a.clone()); // by value
ResourceLoader::singleton().add_resource_format_loader(&a);
ResourceLoader::singleton()
.add_resource_format_loader_ex(b.clone()) // by value
.add_resource_format_loader_ex(&b)
.done();

// Clean up (no leaks).
ResourceLoader::singleton().remove_resource_format_loader(a);
ResourceLoader::singleton().remove_resource_format_loader(b);
ResourceLoader::singleton().remove_resource_format_loader(&a);
ResourceLoader::singleton().remove_resource_format_loader(&b);
}

// ----------------------------------------------------------------------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion itest/rust/src/object_tests/object_swap_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ fn object_subtype_swap_argument_passing(ctx: &TestContext) {

let mut tree = ctx.scene_tree.clone();
expect_panic("pass badly typed Gd<T> to Godot engine API", || {
tree.add_child(node);
tree.add_child(&node);
});

swapped_free!(obj, node2);
Expand Down
6 changes: 3 additions & 3 deletions itest/rust/src/object_tests/object_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ fn object_engine_freed_argument_passing(ctx: &TestContext) {
// Destroy object and then pass it to a Godot engine API.
node.free();
expect_panic("pass freed Gd<T> to Godot engine API (T=Node)", || {
tree.add_child(node2);
tree.add_child(&node2);
});
}

Expand Down Expand Up @@ -325,7 +325,7 @@ fn object_user_freed_argument_passing() {
// Destroy object and then pass it to a Godot engine API (upcast itself works, see other tests).
obj.free();
expect_panic("pass freed Gd<T> to Godot engine API (T=user)", || {
engine.register_singleton("NeverRegistered", obj2);
engine.register_singleton("NeverRegistered", &obj2);
});
}

Expand Down Expand Up @@ -848,7 +848,7 @@ fn object_get_scene_tree(ctx: &TestContext) {
let node = Node3D::new_alloc();

let mut tree = ctx.scene_tree.clone();
tree.add_child(node);
tree.add_child(&node);

let count = tree.get_child_count();
assert_eq!(count, 1);
Expand Down
2 changes: 1 addition & 1 deletion itest/rust/src/object_tests/onready_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ fn init_attribute_node_key_lifecycle() {

let mut child = Node::new_alloc();
child.set_name("child");
obj.add_child(child);
obj.add_child(&child);

obj.notify(NodeNotification::READY);

Expand Down
2 changes: 1 addition & 1 deletion itest/rust/src/object_tests/virtual_methods_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ fn test_format_loader(_test_context: &TestContext) {
.unwrap();
assert!(resource.try_cast::<BoxMesh>().is_ok());

loader.remove_resource_format_loader(format_loader);
loader.remove_resource_format_loader(&format_loader);
}

#[itest]
Expand Down
2 changes: 1 addition & 1 deletion itest/rust/src/register_tests/rpc_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ fn node_enters_tree() {
.get_main_loop()
.unwrap()
.cast::<SceneTree>();
scene_tree.set_multiplayer(MultiplayerApi::create_default_interface());
scene_tree.set_multiplayer(&MultiplayerApi::create_default_interface());
let mut root = scene_tree.get_root().unwrap();
root.add_child(&node);
root.remove_child(&node);
Expand Down

0 comments on commit d2c61db

Please sign in to comment.