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

Fix GDExtension Variant type conversion #75758

Merged

Conversation

Pylgos
Copy link
Contributor

@Pylgos Pylgos commented Apr 6, 2023

Fixes #75757
Fixes godotengine/godot-cpp#1132
Fixes godotengine/godot-cpp#907
Fixes godotengine/godot-cpp#1106

With this PR, VariantTypeConstructor<T>::type_from_variant now does the type conversion from Variant to T. Previously, it only reinterpret_cast the variant data by VariantInternalAccessor<T>::get.

@Pylgos Pylgos requested a review from a team as a code owner April 6, 2023 15:33
@Chaosus Chaosus added this to the 4.1 milestone Apr 6, 2023
@dsnopek
Copy link
Contributor

dsnopek commented Apr 11, 2023

To check if I'm understanding this correctly:

Presently, VariantTypeConstructor<T>::type_from_variant() will assume that the Variant internally already has a value that is type T. When it isn't actually type T, then weird things happen (ala #75757).

With this PR, rather than using VariantInternalAccessor<T>::get(), it'll rely on the operator T() method on Variant to get the value, possibly converting it to T if it isn't already internally T.

Do I have that right?

@dsnopek dsnopek requested a review from a team April 11, 2023 21:02
Copy link
Contributor

@dsnopek dsnopek left a comment

Choose a reason for hiding this comment

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

I just tested the reproduction project on #75757 and I'm able to reproduce the issue. Using the changes in this PR fixes it!

Assuming I'm understanding the changes (as described in my previous comment), this seems good to me. :-)

However, it should still be reviewed by someone on the @godotengine/core or @godotengine/gdextension teams in case this would cause some collateral damage that I'm not aware of.

@Pylgos
Copy link
Contributor Author

Pylgos commented Apr 11, 2023

@dsnopek
Your understanding is correct. Thanks for reviewing this PR.

@@ -1537,7 +1537,7 @@ struct VariantTypeConstructor {
}

_FORCE_INLINE_ static void type_from_variant(void *p_value, void *p_variant) {
*((T *)p_value) = VariantInternalAccessor<T>::get(reinterpret_cast<Variant *>(p_variant));
*((T *)p_value) = *reinterpret_cast<Variant *>(p_variant);
Copy link
Member

Choose a reason for hiding this comment

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

Is there a reason for the C-style cast instead of reinterpret_cast everywhere ?

*reinterpret_cast<T *>p_value = *reinterpret_cast<Variant *>(p_variant);

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know the answer to the question :-) but because that cast isn't added by this PR, I don't think this should block this PR.

There's loads and loads of casts in GDExtension, and more than one bug has been caused by using the inappropriate cast for the situation, so perhaps we need an issue/PR that's dedicated to sorting out all the different casts?

@dsnopek
Copy link
Contributor

dsnopek commented Jun 9, 2023

Given my increased understanding of GDExtension since I wrote my last comment, and the additional testing of this change from #1132, I'm feeling pretty confident that this change is correct. Let's see if the CI agrees with me :-)

Probably should still have someone else from the GDExtension team take a look at it, though - I've added it to the agenda for the next GDExtension meeting.

@akien-mga
Copy link
Member

Would need a rebase to pass CI, last time this PR was updated godot-cpp was mid update and it's now locked to that state.

@Pylgos Pylgos force-pushed the fix-gdextension-variant-construction branch from f4645a9 to d7eb710 Compare June 10, 2023 03:17
@akien-mga akien-mga requested a review from a team June 12, 2023 08:45
@dsnopek
Copy link
Contributor

dsnopek commented Jun 12, 2023

A quick explanation for why I think this change is right for future reviewers:

The functions generated by VariantTypeConstructor<T>::type_from_variant() are used in godot-cpp exclusively for all the T Variant::operator T() methods. This change makes it so that we're also calling the T Variant::operator T() methods on the Godot side (hence converting to the requested type), as opposed to calling VariantInternalAccessor<T>::get() which is used currently (and hence not converting, but just assuming the data is internally already the requested type).

Despite coming from variant_internal.h and the generic name, VariantTypeConstructor<T> appears to only be used by GDExtension, so this change won't have any ramifications outside of GDExtension.

Copy link
Contributor

@dsnopek dsnopek left a comment

Choose a reason for hiding this comment

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

Discussed at the GDExtension meeting, and this change seems fine from the perspective of godot-cpp. It would be good if @Bromeon and @touilleMan could confirm that this won't cause any problems in the Rust or Python bindings. Approved if they say it looks fine!

Copy link
Contributor

@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.

I ran our full CI on commit d7eb710.

All green! ✔️

@akien-mga akien-mga merged commit b8bf28e into godotengine:master Jun 19, 2023
13 checks passed
@akien-mga
Copy link
Member

Thanks!

@Pylgos Pylgos deleted the fix-gdextension-variant-construction branch June 19, 2023 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants