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

Some cleanup and more accurate tracking of safety invariants #603

Merged
merged 3 commits into from Feb 20, 2024

Conversation

lilizoey
Copy link
Member

Probably gonna split this PR up later since the Array-related changes ended up being a lot bigger than i expected. So leaving it as a draft until i do that at least.

Removes some unused traits

From what i can tell, EngineClass and ExportableObject are now actually unused (beyond a test using a method from EngineClass). So i removed them.

Makes Inherits unsafe

We rely on Inherits being implemented correctly for upcast to be safe.

Replace () with NoBase

It seemed weird to use () in this situation, so i made it a dedicated unconstructable type instead.

More accurately track Array's safety invariant

Array's safety invariant is that it only containts values matching its type, but that could very easily be circumvented internally in our code. You could simply call self.as_inner().duplicate(). This PR treats self.as_inner() as equivalent to doing self.assume_type::<Variant>(). This revealed the fact that we actually violated the safety invariant with resize, as it inserts Variant::nil() when increasing the size.

To support this properly i made it possible to mark arbitrary methods in the codegen as unsafe with safety docs, and currently just added all array methods that return VariantArray to that, since they can just bypass safety checks by coercing the array to a `VariantArray.

I removed resize since it can be used to circumvent the safety invariant, instead there's now shrink and resize_with.

@lilizoey lilizoey added bug c: core Core components ub Undefined behavior labels Feb 10, 2024
@GodotRust
Copy link

API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-603

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.

Good catch on Inherits! Also NoBase is a nice way to make things more explicit.


We may want to revisit manually implementing Inherits when it comes to the builder API. Conceptually, it should be possible to inherit from any base in a safe way -- the unsafety can only occur if there are inconsistencies between GodotClass::Base and Inherits.

Probably, a good approach would be to only let the user implement GodotClass by hand, and then have a declarative macro that writes the impl Inherits, just like it is already the case with Bounds. Then using that macro would be safe, but manually implementing Inherits would not -- there'd never be a reason to do the latter though.


Could you add an empty line before each of the // SAFETY: comments (except when it's the start of a block of course)?

godot-codegen/src/generator/builtins.rs Outdated Show resolved Hide resolved
godot-codegen/src/generator/builtins.rs Outdated Show resolved Hide resolved
godot-codegen/src/generator/classes.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/array.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/array.rs Outdated Show resolved Hide resolved
godot-core/src/builtin/array.rs Show resolved Hide resolved
godot-core/src/builtin/array.rs Outdated Show resolved Hide resolved
godot-core/src/obj/traits.rs Outdated Show resolved Hide resolved
itest/rust/src/object_tests/object_test.rs Outdated Show resolved Hide resolved
Comment on lines 531 to 532
// SAFETY: `Object` is a `#[repr(C)]` struct with its first field being the object pointer.
let obj_ptr = unsafe { *(obj as *const Object as *const GDExtensionObjectPtr) };
Copy link
Member

Choose a reason for hiding this comment

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

I assume the reliance on field order here is due to the fact that the fields themselves are private and thus can't be directly accessed?

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, i was gonna just add a #[doc(hidden)] method to Object to do this instead tbh since then i dont need to do this.

Add the ability to add unsafe + safety docs to arbitrary methods through codegen
More accurately track the safety invariant of `Array`:
- Make all methods of `InnerArray` that return `VariantArray` unsafe
- Make `Array::as_inner()` unsafe
- Add `Array::as_inner_ref()` to allow safe usage of immutable methods
- Reword some safety docs
@lilizoey lilizoey force-pushed the refactor/minor-cleanups branch 2 times, most recently from ac01406 to 14c46e6 Compare February 17, 2024 16:51
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.

I think this looks good -- as it's in draft, is there still something you'd like to add here?
Not closely features can also gladly be done in separate PRs 🙂

@lilizoey
Copy link
Member Author

I think this looks good -- as it's in draft, is there still something you'd like to add here? Not closely features can also gladly be done in separate PRs 🙂

it's mostly in draft just cause i wanted to take a final look at it but didn't have much energy to do so for a bit, i'll look over it now tho and just merge if im happy

@lilizoey lilizoey marked this pull request as ready for review February 20, 2024 16:05
@Bromeon
Copy link
Member

Bromeon commented Feb 20, 2024

Sounds good, go ahead merging as soon as you're ready! 👍

@lilizoey lilizoey added this pull request to the merge queue Feb 20, 2024
Merged via the queue into godot-rust:master with commit 3b7c674 Feb 20, 2024
16 checks passed
@lilizoey lilizoey deleted the refactor/minor-cleanups branch February 20, 2024 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug c: core Core components ub Undefined behavior
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants