Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add return values when generating virtual methods #207

Merged
merged 1 commit into from
Apr 5, 2023

Conversation

jbarnoud
Copy link
Contributor

Fixes #190

Some node methods are expected to return values. The corresponding virtual methods, however, do not reflect that.

For instance, this is the virtual method Node.get_configuration_warnings before this commit:

fn get_configuration_warnings(&self) {
    unimplemented!()
}

This is the same method with this commit:

fn get_configuration_warnings(&self) -> PackedStringArray {
    unimplemented!()
}

This commit adapts what I think is the relevant code from
godot_codegen::class_generator::make_method_definition into make_virtual_method.

Note that I am very unfamiliar with most of the code I had to touch here as well as with the project.

Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this PR! 🙂

  1. It looks like you copy-pasted a lot of code from other parts of class_generator.rs. Would it be possible to reuse that code instead, so it's only defined once -- if necessary with extra functions?
  2. Could you maybe add a test that uses a method with a return type? There are existing tests in itest/rust/src/virtual_methods_test.rs.

Also, in the end please squash commits to 1 😉

@Bromeon Bromeon added bug c: engine Godot classes (nodes, resources, ...) labels Mar 28, 2023
@lilizoey
Copy link
Member

lilizoey commented Mar 28, 2023

a minor note, many of these virtual methods will likely not work until #204 is merged. basically any virtual method call that takes/returns anything but pass-by-value types are currently broken (excluding the receiver), which likely includes the one you're referencing too.

as a workaround, string types, arrays, and dictionaries need to have a clone/share std::mem::forget before the function returns. Gd types just do not work though

@jbarnoud
Copy link
Contributor Author

I'll wait for #204 to move on before fixing the PR, then 😃

@jbarnoud
Copy link
Contributor Author

jbarnoud commented Apr 1, 2023

I implemented a basic test that calls an overloaded virtual method. The test passes, but I now get the following warning:

WARNING: ObjectDB instances leaked at exit (run with --verbose for details).
     at: cleanup (core/object/object.cpp:1982)

@SayakS Is this the kind of thing you are fixing on #204, or is it something I need to look at?

@lilizoey
Copy link
Member

lilizoey commented Apr 1, 2023

I implemented a basic test that calls an overloaded virtual method. The test passes, but I now get the following warning:

WARNING: ObjectDB instances leaked at exit (run with --verbose for details).
     at: cleanup (core/object/object.cpp:1982)

@SayakS Is this the kind of thing you are fixing on #204, or is it something I need to look at?

This should be fixed by #204 yes. if you want you can try and see if it does make this test pass, i can't really test it in that PR since it uses a return type. It would actually be pretty good to have tested.

@Bromeon
Copy link
Member

Bromeon commented Apr 2, 2023

Trying with latest CI changes...

bors try

bors bot added a commit that referenced this pull request Apr 2, 2023
@bors
Copy link
Contributor

bors bot commented Apr 2, 2023

try

Build failed:

let output = obj.bind().get_configuration_warnings();
assert!(output.contains("Hello".into()));
assert_eq!(output.len(), 1);
obj.bind_mut().queue_free();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line missing was the cause of the memory leak and, therefore, of the pipeline failing. Another way of solving the memory leak would be to add the obj node to the test_context which, I guess, gets cleaned at the end of the test. I went for queue_free because it looked more concise, but I do not know if there is a recommended practice here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah no that makes sense. nodes outside of the scene tree need to be manually freed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use free() directly, no? If yes, that should be preferred over queue_free().

Also, you can apply that directly on the Gd pointer:

obj.free();

@jbarnoud
Copy link
Contributor Author

jbarnoud commented Apr 3, 2023

I added a test and refactored the code to avoid repetitions. I also rebased against master and squashed the commits. I think this is ready for review.

I haven't seen issues regarding #204. Just to be sure, I tested locally with both this PR and #204 merged together and the tests passed all the same.

The memory leak I encountered earlier had nothing to do with #204, but was due to me not cleaning after myself. See my comment above.

@Bromeon
Copy link
Member

Bromeon commented Apr 3, 2023

bors try

bors bot added a commit that referenced this pull request Apr 3, 2023
@bors
Copy link
Contributor

bors bot commented Apr 3, 2023

try

Build succeeded:

bors bot added a commit that referenced this pull request Apr 3, 2023
Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Looks mostly good to me 🙂

At first sight I was a bit concerned that the is_virtual code path in make_function_definition() adds a lot of special-casing for relatively few functionality, as it doesn't use a lot of the function codegen logic. But overall I think it's nice to handle those things in one place, and it can also prevent bugs like this one. Thanks for the refactoring! 👍

Comment on lines 961 to 965
(true, _, _) => {
quote! {
unimplemented!()
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you maybe move this to the top?
Then it's immediately clear that no more statements handle is_virtual == true.

let output = obj.bind().get_configuration_warnings();
assert!(output.contains("Hello".into()));
assert_eq!(output.len(), 1);
obj.bind_mut().queue_free();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use free() directly, no? If yes, that should be preferred over queue_free().

Also, you can apply that directly on the Gd pointer:

obj.free();

@jbarnoud
Copy link
Contributor Author

jbarnoud commented Apr 4, 2023

Done 👍

Fixes godot-rust#190

Some node methods are expected to return values. The corresponding
virtual methods, however, do not reflect that.

For instance, this is the virtual method `Node.get_configuration_warnings` before this commit:

```rust
fn get_configuration_warnings(&self) {
    unimplemented!()
}
```

This is the same method with this commit:

```rust
fn get_configuration_warnings(&self) -> PackedStringArray {
    unimplemented!()
}
```

This commit makes
`godot_codegen::clas_generator::make_function_definition` and
`make_return` aware of virtual method. It also adds a test making sure
we can call a virtual method that has a return value.
Copy link
Member

@Bromeon Bromeon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot!

bors r+

@bors
Copy link
Contributor

bors bot commented Apr 5, 2023

Build succeeded:

@bors bors bot merged commit 04c2323 into godot-rust:master Apr 5, 2023
5 checks passed
@jbarnoud jbarnoud deleted the virtual_method_returns branch April 5, 2023 08:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug c: engine Godot classes (nodes, resources, ...)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Virtual Methods missing return type
3 participants