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

godot-ffi: lazy-function-tables broken with experimental-threads #1025

Open
feefladder opened this issue Jan 23, 2025 · 1 comment
Open

godot-ffi: lazy-function-tables broken with experimental-threads #1025

feefladder opened this issue Jan 23, 2025 · 1 comment
Labels
bug c: tooling CI, automation, tools

Comments

@feefladder
Copy link

feefladder commented Jan 23, 2025

Not sure if already documented,
I was trying to build a project using gdext_coroutines and then the behaviour was really weird: this bug would only show up on branch="master" and not on rev=<last commit hash>

The compiler complains that the lazily initiated static BINDING is not Sync:

long compiler output
error[E0277]: `RefCell<table_servers_classes::InnerTable>` cannot be shared between threads safely
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:27:25
    |
27  |         static BINDING: BindingStorage = BindingStorage {
    |                         ^^^^^^^^^^^^^^ `RefCell<table_servers_classes::InnerTable>` cannot be shared between threads safely
    |
    = help: within `table_servers_classes::ClassServersMethodTable`, the trait `Sync` is not implemented for `RefCell<table_servers_classes::InnerTable>`, which is required by `BindingStorage: Sync`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: required because it appears within the type `table_servers_classes::ClassServersMethodTable`
   --> /home/user/git/afgrust/rust/target/debug/build/godot-ffi-ef451ebf4bfe53c8/out/table_servers_classes.rs:7:12
    |
7   | pub struct ClassServersMethodTable {
    |            ^^^^^^^^^^^^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<table_servers_classes::ClassServersMethodTable>` to implement `Sync`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:529:33
    |
529 |     unsafe impl<T: Send + Sync> Sync for ManualInitCell<T> {}
    |                           ----  ^^^^     ^^^^^^^^^^^^^^^^^
    |                           |
    |                           unsatisfied trait bound introduced here
note: required because it appears within the type `binding::GodotBinding`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/mod.rs:32:19
    |
32  | pub(crate) struct GodotBinding {
    |                   ^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<binding::GodotBinding>` to implement `Sync`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:529:33
    |
529 |     unsafe impl<T: Send + Sync> Sync for ManualInitCell<T> {}
    |                           ----  ^^^^     ^^^^^^^^^^^^^^^^^
    |                           |
    |                           unsatisfied trait bound introduced here
note: required because it appears within the type `BindingStorage`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:19:19
    |
19  | pub(super) struct BindingStorage {
    |                   ^^^^^^^^^^^^^^
    = note: shared static variables must have a type that implements `Sync`

error[E0277]: `RefCell<table_scene_classes::InnerTable>` cannot be shared between threads safely
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:27:25
    |
27  |         static BINDING: BindingStorage = BindingStorage {
    |                         ^^^^^^^^^^^^^^ `RefCell<table_scene_classes::InnerTable>` cannot be shared between threads safely
    |
    = help: within `table_scene_classes::ClassSceneMethodTable`, the trait `Sync` is not implemented for `RefCell<table_scene_classes::InnerTable>`, which is required by `BindingStorage: Sync`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: required because it appears within the type `table_scene_classes::ClassSceneMethodTable`
   --> /home/user/git/afgrust/rust/target/debug/build/godot-ffi-ef451ebf4bfe53c8/out/table_scene_classes.rs:7:12
    |
7   | pub struct ClassSceneMethodTable {
    |            ^^^^^^^^^^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<table_scene_classes::ClassSceneMethodTable>` to implement `Sync`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:529:33
    |
529 |     unsafe impl<T: Send + Sync> Sync for ManualInitCell<T> {}
    |                           ----  ^^^^     ^^^^^^^^^^^^^^^^^
    |                           |
    |                           unsatisfied trait bound introduced here
note: required because it appears within the type `binding::GodotBinding`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/mod.rs:32:19
    |
32  | pub(crate) struct GodotBinding {
    |                   ^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<binding::GodotBinding>` to implement `Sync`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:529:33
    |
529 |     unsafe impl<T: Send + Sync> Sync for ManualInitCell<T> {}
    |                           ----  ^^^^     ^^^^^^^^^^^^^^^^^
    |                           |
    |                           unsatisfied trait bound introduced here
note: required because it appears within the type `BindingStorage`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:19:19
    |
19  | pub(super) struct BindingStorage {
    |                   ^^^^^^^^^^^^^^
    = note: shared static variables must have a type that implements `Sync`

error[E0277]: `RefCell<table_editor_classes::InnerTable>` cannot be shared between threads safely
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:27:25
    |
27  |         static BINDING: BindingStorage = BindingStorage {
    |                         ^^^^^^^^^^^^^^ `RefCell<table_editor_classes::InnerTable>` cannot be shared between threads safely
    |
    = help: within `table_editor_classes::ClassEditorMethodTable`, the trait `Sync` is not implemented for `RefCell<table_editor_classes::InnerTable>`, which is required by `BindingStorage: Sync`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: required because it appears within the type `table_editor_classes::ClassEditorMethodTable`
   --> /home/user/git/afgrust/rust/target/debug/build/godot-ffi-ef451ebf4bfe53c8/out/table_editor_classes.rs:7:12
    |
7   | pub struct ClassEditorMethodTable {
    |            ^^^^^^^^^^^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<table_editor_classes::ClassEditorMethodTable>` to implement `Sync`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:529:33
    |
529 |     unsafe impl<T: Send + Sync> Sync for ManualInitCell<T> {}
    |                           ----  ^^^^     ^^^^^^^^^^^^^^^^^
    |                           |
    |                           unsatisfied trait bound introduced here
note: required because it appears within the type `binding::GodotBinding`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/mod.rs:32:19
    |
32  | pub(crate) struct GodotBinding {
    |                   ^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<binding::GodotBinding>` to implement `Sync`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:529:33
    |
529 |     unsafe impl<T: Send + Sync> Sync for ManualInitCell<T> {}
    |                           ----  ^^^^     ^^^^^^^^^^^^^^^^^
    |                           |
    |                           unsatisfied trait bound introduced here
note: required because it appears within the type `BindingStorage`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:19:19
    |
19  | pub(super) struct BindingStorage {
    |                   ^^^^^^^^^^^^^^
    = note: shared static variables must have a type that implements `Sync`

error[E0277]: `RefCell<table_builtins::InnerTable>` cannot be shared between threads safely
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:27:25
    |
27  |         static BINDING: BindingStorage = BindingStorage {
    |                         ^^^^^^^^^^^^^^ `RefCell<table_builtins::InnerTable>` cannot be shared between threads safely
    |
    = help: within `table_builtins::BuiltinMethodTable`, the trait `Sync` is not implemented for `RefCell<table_builtins::InnerTable>`, which is required by `BindingStorage: Sync`
    = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead
note: required because it appears within the type `table_builtins::BuiltinMethodTable`
   --> /home/user/git/afgrust/rust/target/debug/build/godot-ffi-ef451ebf4bfe53c8/out/table_builtins.rs:7:12
    |
7   | pub struct BuiltinMethodTable {
    |            ^^^^^^^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<table_builtins::BuiltinMethodTable>` to implement `Sync`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:529:33
    |
529 |     unsafe impl<T: Send + Sync> Sync for ManualInitCell<T> {}
    |                           ----  ^^^^     ^^^^^^^^^^^^^^^^^
    |                           |
    |                           unsatisfied trait bound introduced here
note: required because it appears within the type `binding::GodotBinding`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/mod.rs:32:19
    |
32  | pub(crate) struct GodotBinding {
    |                   ^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<binding::GodotBinding>` to implement `Sync`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:529:33
    |
529 |     unsafe impl<T: Send + Sync> Sync for ManualInitCell<T> {}
    |                           ----  ^^^^     ^^^^^^^^^^^^^^^^^
    |                           |
    |                           unsatisfied trait bound introduced here
note: required because it appears within the type `BindingStorage`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:19:19
    |
19  | pub(super) struct BindingStorage {
    |                   ^^^^^^^^^^^^^^
    = note: shared static variables must have a type that implements `Sync`

error[E0277]: `*const u8` cannot be sent between threads safely
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:27:25
    |
27  |         static BINDING: BindingStorage = BindingStorage {
    |                         ^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
    |
    = help: within `Opaque<8>`, the trait `Send` is not implemented for `*const u8`, which is required by `BindingStorage: Sync`
note: required because it appears within the type `PhantomData<*const u8>`
   --> /home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/marker.rs:753:12
    |
753 | pub struct PhantomData<T: ?Sized>;
    |            ^^^^^^^^^^^
note: required because it appears within the type `Opaque<8>`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/opaque.rs:25:12
    |
25  | pub struct Opaque<const N: usize> {
    |            ^^^^^^
    = note: required for `Unique<Opaque<8>>` to implement `Send`
note: required because it appears within the type `Box<Opaque<8>>`
   --> /home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/boxed.rs:234:12
    |
234 | pub struct Box<
    |            ^^^
    = note: required because it appears within the type `(&'static str, Box<Opaque<8>>)`
    = note: required for `hashbrown::raw::RawTable<(&'static str, Box<Opaque<8>>)>` to implement `Send`
note: required because it appears within the type `hashbrown::map::HashMap<&'static str, Box<Opaque<8>>, RandomState>`
   --> /rust/deps/hashbrown-0.15.0/src/map.rs:185:12
note: required because it appears within the type `HashMap<&'static str, Box<Opaque<8>>>`
   --> /home/user/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/collections/hash/map.rs:211:12
    |
211 | pub struct HashMap<K, V, S = RandomState> {
    |            ^^^^^^^
note: required because it appears within the type `StringCache<'static>`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/string_cache.rs:15:12
    |
15  | pub struct StringCache<'a> {
    |            ^^^^^^^^^^^
note: required because it appears within the type `table_servers_classes::InnerTable`
   --> /home/user/git/afgrust/rust/target/debug/build/godot-ffi-ef451ebf4bfe53c8/out/table_servers_classes.rs:4:8
    |
4   | struct InnerTable {
    |        ^^^^^^^^^^
    = note: required for `RefCell<table_servers_classes::InnerTable>` to implement `Send`
note: required because it appears within the type `table_servers_classes::ClassServersMethodTable`
   --> /home/user/git/afgrust/rust/target/debug/build/godot-ffi-ef451ebf4bfe53c8/out/table_servers_classes.rs:7:12
    |
7   | pub struct ClassServersMethodTable {
    |            ^^^^^^^^^^^^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<table_servers_classes::ClassServersMethodTable>` to implement `Send`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:531:26
    |
531 |     unsafe impl<T: Send> Send for ManualInitCell<T> {}
    |                    ----  ^^^^     ^^^^^^^^^^^^^^^^^
    |                    |
    |                    unsatisfied trait bound introduced here
note: required because it appears within the type `binding::GodotBinding`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/mod.rs:32:19
    |
32  | pub(crate) struct GodotBinding {
    |                   ^^^^^^^^^^^^
note: required for `manual_init_cell::ManualInitCell<binding::GodotBinding>` to implement `Sync`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/toolbox.rs:529:33
    |
529 |     unsafe impl<T: Send + Sync> Sync for ManualInitCell<T> {}
    |                    ----         ^^^^     ^^^^^^^^^^^^^^^^^
    |                    |
    |                    unsatisfied trait bound introduced here
note: required because it appears within the type `BindingStorage`
   --> /home/user/.cargo/git/checkouts/gdext-76630c89719e160c/7461251/godot-ffi/src/binding/multi_threaded.rs:19:19
    |
19  | pub(super) struct BindingStorage {
    |                   ^^^^^^^^^^^^^^
    = note: shared static variables must have a type that implements `Sync`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `godot-ffi` (lib) due to 5 previous errors
warning: build failed, waiting for other jobs to finish...

I've tracked it down to these two features being incompatible...

@feefladder feefladder changed the title godot-ffi: lazy-function-tables broken with `experimental-threads" godot-ffi: lazy-function-tables broken with experimental-threads Jan 23, 2025
@Bromeon
Copy link
Member

Bromeon commented Jan 23, 2025

This combination is explicitly not supported:

gdext/godot/src/lib.rs

Lines 146 to 147 in 97b66ec

#[cfg(all(feature = "lazy-function-tables", feature = "experimental-threads"))]
compile_error!("Thread safety for lazy function pointers is not yet implemented.");

But it looks like this check is happening too late (godot crate), because your error happens already in godot-ffi. So we should fix that.

@Bromeon Bromeon added bug c: tooling CI, automation, tools labels Jan 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug c: tooling CI, automation, tools
Projects
None yet
Development

No branches or pull requests

2 participants