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

Can't build druid-shell on Mac with error: *const Class cannot be sent between threads safely #2211

Closed
Steve-xmh opened this issue Jun 28, 2022 · 9 comments
Labels
bug does not behave the way it is supposed to shell/mac concerns the macOS backend

Comments

@Steve-xmh
Copy link
Contributor

I was using stable rust compiler stable-x86_64-apple-darwin - rustc 1.61.0 (fe5b13d68 2022-05-18) (from rustc 1.61.0 (fe5b13d68 2022-05-18)) and try to build my program with druid (Commit 7d08672), but some errors occured.

I've already checked #176 which had the same problem, but upgrading rustc doesn't work for me as I'm using Github Action.

Error output:

error[E0277]: `*const Class` cannot be sent between threads safely
--> /Users/runner/.cargo/git/checkouts/druid-f71533f3d81c0bc8/7d08672/druid-shell/src/backend/mac/application.rs:160:1
|
160| /lazy_static! {
161| |    static ref APP_DELEGATE: AppDelegate = unsafe {
162| |        let mut decl = ClassDecl::new("DruidAppDelegate", class!(NSObject))
163| |            .expect("App Delegate definition failed");
...|
176| |    };
177| |}
| |_^`*const Class` cannot be sent between threads safely
|
= help: within `AppDelegate`, the trait `Send` is not implemented for `*const Class`
note: required because it appears within the type `AppDelegate`
--> /Users/runner/.cargo/git/checkouts/druid-f71533f3d81c0bc8/7d08672/druid-shell/src/backend/mac/application.rs:157:8
|
157| struct AppDelegate(*const Class);
| ^^^^^^^^^^^
= note: required because of the requirements on the impl of `Sync` for `spin::once::Once<AppDelegate>`
= note: required because it appears within the type `lazy_static::lazy::Lazy<AppDelegate>`
= note: shared static variables must have a type that implements `Sync`
= note: this error originates in the macro `__lazy_static_create` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: `*const Class` cannot be sent between threads safely
--> /Users/runner/.cargo/git/checkouts/druid-f71533f3d81c0bc8/7d08672/druid-shell/src/backend/mac/window.rs:339:1
|
339| /lazy_static! {
340| |    static ref VIEW_CLASS: ViewClass = unsafe {
341| |        let mut decl = ClassDecl::new("DruidView", class!(NSView)).expect("View class defined");
342| |        decl.add_ivar::<*mut c_void>("viewState");
...|
524| |    };
525| |}
| |_^`*const Class` cannot be sent between threads safely
|
= help: within `ViewClass`, the trait `Send` is not implemented for `*const Class`
note: required because it appears within the type `ViewClass`
--> /Users/runner/.cargo/git/checkouts/druid-f71533f3d81c0bc8/7d08672/druid-shell/src/backend/mac/window.rs:336:8
|
336| struct ViewClass(*const Class);
| ^^^^^^^^^
= note: required because of the requirements on the impl of `Sync` for `spin::once::Once<ViewClass>`
= note: required because it appears within the type `lazy_static::lazy::Lazy<ViewClass>`
= note: shared static variables must have a type that implements `Sync`
= note: this error originates in the macro `__lazy_static_create` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0277]: `*const Class` cannot be sent between threads safely
--> /Users/runner/.cargo/git/checkouts/druid-f71533f3d81c0bc8/7d08672/druid-shell/src/backend/mac/window.rs:587:1
|
587| /lazy_static! {
588| |    static ref WINDOW_CLASS: WindowClass = unsafe {
589| |        let mut decl =
590| |            ClassDecl::new("DruidWindow", class!(NSWindow)).expect("Window class defined");
...|
599| |    };
600| |}
| |_^`*const Class` cannot be sent between threads safely
|
= help: within `WindowClass`, the trait `Send` is not implemented for `*const Class`
note: required because it appears within the type `WindowClass`
--> /Users/runner/.cargo/git/checkouts/druid-f71533f3d81c0bc8/7d08672/druid-shell/src/backend/mac/window.rs:584:8
|
584| struct WindowClass(*const Class);
| ^^^^^^^^^^^
= note: required because of the requirements on the impl of `Sync` for `spin::once::Once<WindowClass>`
= note: required because it appears within the type `lazy_static::lazy::Lazy<WindowClass>`
= note: shared static variables must have a type that implements `Sync`
= note: this error originates in the macro `__lazy_static_create` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0277`.
error: could not compile `druid-shell` due to 3 previous errors

I've never used MacOS before, so please remind me if there's something I don't know. Thanks!

@Steve-xmh
Copy link
Contributor Author

I tried to add Send trait to those structs and it passed check and building successfully. Or should we have a PR for this?

@xStrom
Copy link
Member

xStrom commented Jun 30, 2022

  • What macOS version are you using?
  • What exact command line did you use to attempt the build? (e.g. cargo build or cargo build --manifest.....)

I see you mention using GitHub Actions, but we use GitHub actions as well, and it builds.

@Steve-xmh
Copy link
Contributor Author

Steve-xmh commented Jun 30, 2022

  • What macOS version are you using?
  • What exact command line did you use to attempt the build? (e.g. cargo build or cargo build --manifest.....)

I see you mention using GitHub Actions, but we use GitHub actions as well, and it builds.

I'm using Github Actions with machine macOS-latest (or macOS Big Sur 11 ), then I ran cargo build --release --target=x86_64-apple-darwin --verbose and that's all.

I tried to build a minimal druid program with only druid as the dependencies and it also builds fine. So maybe there's something strange in my project that made rustc avoid parsing the Sync trait and throw that error.

As I said above, it will goes well if I added Send trait implementations to those struct. So should we try to add and fix it?

I just pretty confused because I never modify or patch dependencies but it really happened when I first try to build it on Mac and I don't know what is wrong.

@Steve-xmh
Copy link
Contributor Author

Steve-xmh commented Jun 30, 2022

Maybe I found the reason, after I checked dependencies tree by cargo tree I found this:

├── druid v0.7.0 (https://github.com/linebender/druid.git#bc1877b7)
│   ├── druid-derive v0.4.0 (proc-macro) (https://github.com/linebender/druid.git#bc1877b7)
│   │   ├── proc-macro2 v1.0.40 (*)
│   │   ├── quote v1.0.20 (*)
│   │   └── syn v1.0.98 (*)
│   ├── druid-shell v0.7.0 (https://github.com/linebender/druid.git#bc1877b7)
│   │   ├── anyhow v1.0.58
│   │   ├── bitflags v1.3.2
│   │   ├── block v0.1.6
│   │   ├── cfg-if v1.0.0
│   │   ├── cocoa v0.24.0
│   │   │   ├── bitflags v1.3.2
│   │   │   ├── block v0.1.6
│   │   │   ├── cocoa-foundation v0.1.0
│   │   │   │   ├── bitflags v1.3.2
│   │   │   │   ├── block v0.1.6
│   │   │   │   ├── core-foundation v0.9.3
│   │   │   │   │   ├── core-foundation-sys v0.8.3
│   │   │   │   │   └── libc v0.2.126
│   │   │   │   ├── core-graphics-types v0.1.1
│   │   │   │   │   ├── bitflags v1.3.2
│   │   │   │   │   ├── core-foundation v0.9.3 (*)
│   │   │   │   │   ├── foreign-types v0.3.2
│   │   │   │   │   │   └── foreign-types-shared v0.1.1
│   │   │   │   │   └── libc v0.2.126
│   │   │   │   ├── foreign-types v0.3.2 (*)
│   │   │   │   ├── libc v0.2.126
│   │   │   │   └── objc v0.2.7
│   │   │   │       └── malloc_buf v0.0.6
│   │   │   │           └── libc v0.2.126
│   │   │   ├── core-foundation v0.9.3 (*)
│   │   │   ├── core-graphics v0.22.3
│   │   │   │   ├── bitflags v1.3.2
│   │   │   │   ├── core-foundation v0.9.3 (*)
│   │   │   │   ├── core-graphics-types v0.1.1 (*)
│   │   │   │   ├── foreign-types v0.3.2 (*)
│   │   │   │   └── libc v0.2.126
│   │   │   ├── foreign-types v0.3.2 (*)
│   │   │   ├── libc v0.2.126
│   │   │   └── objc v0.2.7 (*)
│   │   ├── core-graphics v0.22.3 (*)
│   │   ├── foreign-types v0.3.2 (*)
│   │   ├── instant v0.1.12
│   │   │   └── cfg-if v1.0.0
│   │   ├── keyboard-types v0.6.2
│   │   │   └── bitflags v1.3.2
│   │   ├── kurbo v0.8.3
│   │   │   ├── arrayvec v0.7.2
│   │   │   └── serde v1.0.137 (*)
│   │   ├── lazy_static v1.4.0 #                <-- Here's the lazy_static
│   │   │   └── spin v0.5.2 #                   <-- But it uses spin that only be enabled by feature `spin_no_std`
│   │   ├── objc v0.2.7 (*)
│   │   ├── piet-common v0.5.0
│   │   │   ├── cfg-if v1.0.0
│   │   │   ├── core-graphics v0.22.3 (*)
│   │   │   ├── piet v0.5.0
│   │   │   │   ├── kurbo v0.8.3 (*)
│   │   │   │   └── unic-bidi v0.9.0
│   │   │   │       ├── matches v0.1.9
│   │   │   │       └── unic-ucd-bidi v0.9.0
│   │   │   │           ├── unic-char-property v0.9.0
│   │   │   │           │   └── unic-char-range v0.9.0
│   │   │   │           ├── unic-char-range v0.9.0
│   │   │   │           └── unic-ucd-version v0.9.0
│   │   │   │               └── unic-common v0.9.0
│   │   │   └── piet-coregraphics v0.5.0
│   │   │       ├── core-foundation v0.9.3 (*)
│   │   │       ├── core-foundation-sys v0.8.3
│   │   │       ├── core-graphics v0.22.3 (*)
│   │   │       ├── core-text v19.2.0
│   │   │       │   ├── core-foundation v0.9.3 (*)
│   │   │       │   ├── core-graphics v0.22.3 (*)
│   │   │       │   ├── foreign-types v0.3.2 (*)
│   │   │       │   └── libc v0.2.126
│   │   │       ├── foreign-types v0.3.2 (*)
│   │   │       └── piet v0.5.0 (*)
│   │   ├── time v0.3.11 (*)
│   │   └── tracing v0.1.35 (*)
│   ├── fluent-bundle v0.15.2
│   │   ├── fluent-langneg v0.13.0
│   │   │   └── unic-langid v0.9.0
│   │   │       └── unic-langid-impl v0.9.0
│   │   │           └── tinystr v0.3.4
│   │   ├── fluent-syntax v0.11.0
│   │   │   └── thiserror v1.0.31 (*)
│   │   ├── intl-memoizer v0.5.1
│   │   │   ├── type-map v0.4.0
│   │   │   │   └── rustc-hash v1.1.0
│   │   │   └── unic-langid v0.9.0 (*)
│   │   ├── intl_pluralrules v7.0.1
│   │   │   ├── tinystr v0.3.4
│   │   │   └── unic-langid v0.9.0 (*)
│   │   ├── rustc-hash v1.1.0
│   │   ├── self_cell v0.10.2
│   │   ├── smallvec v1.9.0
│   │   └── unic-langid v0.9.0 (*)
│   ├── fluent-langneg v0.13.0 (*)
│   ├── fluent-syntax v0.11.0 (*)
│   ├── fnv v1.0.7
│   ├── im v15.1.0
│   │   ├── bitmaps v2.1.0
│   │   │   └── typenum v1.15.0
│   │   ├── rand_core v0.6.3 (*)
│   │   ├── rand_xoshiro v0.6.0
│   │   │   └── rand_core v0.6.3 (*)
│   │   ├── serde v1.0.137 (*)
│   │   ├── sized-chunks v0.6.5
│   │   │   ├── bitmaps v2.1.0 (*)
│   │   │   └── typenum v1.15.0
│   │   └── typenum v1.15.0
│   │   [build-dependencies]
│   │   └── version_check v0.9.4
│   ├── instant v0.1.12 (*)
│   ├── tracing v0.1.35 (*)
│   ├── tracing-subscriber v0.3.12
│   │   ├── ansi_term v0.12.1
│   │   ├── sharded-slab v0.1.4
│   │   │   └── lazy_static v1.4.0 (*)
│   │   ├── thread_local v1.1.4
│   │   │   └── once_cell v1.12.0
│   │   └── tracing-core v0.1.28 (*)
│   ├── unic-langid v0.9.0 (*)
│   ├── unicode-segmentation v1.9.0
│   └── xi-unicode v0.3.0

It uses crate spin to implement Lazy, and the type spin::once::Once requires the type to implement Send to work well.

It may not a bug from druid-shell itself (can it be Cargo's?), but I still want to figure out how to solve it. :(

@xStrom
Copy link
Member

xStrom commented Jul 1, 2022

Excellent investigation! I can now reproduce the error by manually enabling the spin_no_std feature on lazy_static. Druid by itself does not enable this feature, but if some other library in your project enables that feature, this error will appear.

This is definitely an issue with the lazy_static crate, they are doing it wrong. Cargo features need to be additive, and there is even a section in the Cargo reference manual about this:

For example, if you want to optionally support no_std environments, do not use a no_std feature. Instead, use a std feature that enables std.

I reported it to them in lazy-static.rs#204. Hopefully the maintainers care and have time.

However we don't have to wait for them to react. We should definitely fight against this surprise error from our side too. So it seems that there are three types that are lacking Send and all of them are *const. They already implement Sync. Given that, I think it is safe to also add Send.

If you submit a PR here that adds Send to these three types, I will review and accept it.

@xStrom xStrom added bug does not behave the way it is supposed to shell/mac concerns the macOS backend labels Jul 1, 2022
@raphlinus
Copy link
Contributor

We can switch from lazy_static to once_cell as one possibility.

@Steve-xmh
Copy link
Contributor Author

Excellent investigation! I can now reproduce the error by manually enabling the spin_no_std feature on lazy_static. Druid by itself does not enable this feature, but if some other library in your project enables that feature, this error will appear.

This is definitely an issue with the lazy_static crate, they are doing it wrong. Cargo features need to be additive, and there is even a section in the Cargo reference manual about this:

For example, if you want to optionally support no_std environments, do not use a no_std feature. Instead, use a std feature that enables std.

I reported it to them in lazy-static.rs#204. Hopefully the maintainers care and have time.

However we don't have to wait for them to react. We should definitely fight against this surprise error from our side too. So it seems that there are three types that are lacking Send and all of them are *const. They already implement Sync. Given that, I think it is safe to also add Send.

If you submit a PR here that adds Send to these three types, I will review and accept it.

Thank you! I'll prepare a PR for fixing this temporary problem!

@xStrom
Copy link
Member

xStrom commented Jul 1, 2022

We can switch from lazy_static to once_cell as one possibility.

That is a very interesting option. I quickly skimmed over their docs and Cargo.toml and on the surface it looks just a straight up superior library. I'll dig a bit deeper.

@Steve-xmh
Copy link
Contributor Author

This issue was fixed in #2214 so I closed this. Open a new issue to discuss about using once_cell if you want so. Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug does not behave the way it is supposed to shell/mac concerns the macOS backend
Projects
None yet
Development

No branches or pull requests

3 participants