Skip to content

Commit 639aeb4

Browse files
authored
Merge pull request #424 from godot-rust/qol/experimental-features
Feature-gate Godot experimental APIs
2 parents e7cafaa + 00a9ac2 commit 639aeb4

File tree

10 files changed

+35
-29
lines changed

10 files changed

+35
-29
lines changed

.github/workflows/full-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ jobs:
217217
os: ubuntu-20.04
218218
artifact-name: linux-nightly
219219
godot-binary: godot.linuxbsd.editor.dev.x86_64
220-
rust-extra-args: --features godot/custom-godot,godot/threads,godot/serde
220+
rust-extra-args: --features godot/custom-godot,godot/experimental-threads,godot/serde
221221

222222
# Linux compat
223223

.github/workflows/minimal-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ jobs:
149149
os: ubuntu-20.04
150150
artifact-name: linux-nightly
151151
godot-binary: godot.linuxbsd.editor.dev.x86_64
152-
rust-extra-args: --features godot/custom-godot,godot/threads,godot/serde
152+
rust-extra-args: --features godot/custom-godot,godot/experimental-threads,godot/serde
153153

154154
# Linux compat
155155

godot-codegen/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ codegen-fmt = []
1313
codegen-full = []
1414
double-precision = []
1515
custom-godot = ["godot-bindings/custom-godot"]
16+
experimental-godot-api = []
1617

1718
[dependencies]
1819
godot-bindings = { path = "../godot-bindings" }

godot-codegen/src/special_cases.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,12 @@ pub(crate) fn is_deleted(class_name: &TyName, method: &ClassMethod, ctx: &mut Co
4444

4545
#[rustfmt::skip]
4646
pub(crate) fn is_class_deleted(class_name: &TyName) -> bool {
47-
let class_name = class_name.godot_ty.as_str();
48-
49-
// TODO feature-gate experimental classes.
50-
/*
47+
// Exclude experimental APIs unless opted-in.
5148
if !cfg!(feature = "experimental-godot-api") && is_class_experimental(class_name) {
5249
return true;
5350
}
54-
*/
51+
52+
let class_name = class_name.godot_ty.as_str();
5553

5654
// OpenXR has not been available for macOS before 4.2.
5755
// See e.g. https://github.com/GodotVR/godot-xr-tools/issues/479.
@@ -105,7 +103,6 @@ pub(crate) fn is_class_deleted(class_name: &TyName) -> bool {
105103
}
106104

107105
#[rustfmt::skip]
108-
#[allow(dead_code)] // remove once used.
109106
fn is_class_experimental(class_name: &TyName) -> bool {
110107
// These classes are currently hardcoded, but the information is available in Godot's doc/classes directory.
111108
// The XML file contains a property <class name="NavigationMesh" ... is_experimental="true">.

godot-core/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ codegen-fmt = ["godot-ffi/codegen-fmt", "godot-codegen/codegen-fmt"]
1414
codegen-full = ["godot-codegen/codegen-full"]
1515
double-precision = ["godot-codegen/double-precision"]
1616
custom-godot = ["godot-ffi/custom-godot", "godot-codegen/custom-godot"]
17-
threads = []
17+
experimental-godot-api = ["godot-codegen/experimental-godot-api"]
18+
experimental-threads = []
1819

1920
[dependencies]
2021
godot-ffi = { path = "../godot-ffi" }

godot-core/src/obj/guards.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,32 @@
44
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
55
*/
66

7-
#[cfg(not(feature = "threads"))]
7+
#[cfg(not(feature = "experimental-threads"))]
88
use std::cell;
99
use std::fmt::Debug;
1010
use std::ops::{Deref, DerefMut};
11-
#[cfg(feature = "threads")]
11+
#[cfg(feature = "experimental-threads")]
1212
use std::sync;
1313

1414
/// Immutably/shared bound reference guard for a [`Gd`][crate::obj::Gd] smart pointer.
1515
///
1616
/// See [`Gd::bind`][crate::obj::Gd::bind] for usage.
1717
#[derive(Debug)]
1818
pub struct GdRef<'a, T> {
19-
#[cfg(not(feature = "threads"))]
19+
#[cfg(not(feature = "experimental-threads"))]
2020
cell_ref: cell::Ref<'a, T>,
2121

22-
#[cfg(feature = "threads")]
22+
#[cfg(feature = "experimental-threads")]
2323
cell_ref: sync::RwLockReadGuard<'a, T>,
2424
}
2525

2626
impl<'a, T> GdRef<'a, T> {
27-
#[cfg(not(feature = "threads"))]
27+
#[cfg(not(feature = "experimental-threads"))]
2828
pub(crate) fn from_cell(cell_ref: cell::Ref<'a, T>) -> Self {
2929
Self { cell_ref }
3030
}
3131

32-
#[cfg(feature = "threads")]
32+
#[cfg(feature = "experimental-threads")]
3333
pub(crate) fn from_cell(cell_ref: sync::RwLockReadGuard<'a, T>) -> Self {
3434
Self { cell_ref }
3535
}
@@ -52,20 +52,20 @@ impl<T> Deref for GdRef<'_, T> {
5252
/// See [`Gd::bind_mut`][crate::obj::Gd::bind_mut] for usage.
5353
#[derive(Debug)]
5454
pub struct GdMut<'a, T> {
55-
#[cfg(not(feature = "threads"))]
55+
#[cfg(not(feature = "experimental-threads"))]
5656
cell_ref: cell::RefMut<'a, T>,
5757

58-
#[cfg(feature = "threads")]
58+
#[cfg(feature = "experimental-threads")]
5959
cell_ref: sync::RwLockWriteGuard<'a, T>,
6060
}
6161

6262
impl<'a, T> GdMut<'a, T> {
63-
#[cfg(not(feature = "threads"))]
63+
#[cfg(not(feature = "experimental-threads"))]
6464
pub(crate) fn from_cell(cell_ref: cell::RefMut<'a, T>) -> Self {
6565
Self { cell_ref }
6666
}
6767

68-
#[cfg(feature = "threads")]
68+
#[cfg(feature = "experimental-threads")]
6969
pub(crate) fn from_cell(cell_ref: sync::RwLockWriteGuard<'a, T>) -> Self {
7070
Self { cell_ref }
7171
}

godot-core/src/storage.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ pub enum Lifecycle {
1818
Dead, // reading this would typically already be too late, only best-effort in case of UB
1919
}
2020

21-
#[cfg(not(feature = "threads"))]
21+
#[cfg(not(feature = "experimental-threads"))]
2222
pub(crate) use single_threaded::*;
2323

24-
#[cfg(feature = "threads")]
24+
#[cfg(feature = "experimental-threads")]
2525
pub(crate) use multi_threaded::*;
2626

27-
#[cfg(not(feature = "threads"))]
27+
#[cfg(not(feature = "experimental-threads"))]
2828
mod single_threaded {
2929
use std::any::type_name;
3030
use std::cell;
@@ -107,7 +107,7 @@ mod single_threaded {
107107
}
108108
}
109109

110-
#[cfg(feature = "threads")]
110+
#[cfg(feature = "experimental-threads")]
111111
mod multi_threaded {
112112
use std::any::type_name;
113113
use std::sync;
@@ -219,7 +219,7 @@ mod multi_threaded {
219219
// This type can be accessed concurrently from multiple threads, so it should be Sync. That implies however that T must be Sync too
220220
// (and possibly Send, because with `&mut` access, a `T` can be extracted as a value using mem::take() etc.).
221221
// Which again means that we need to infest half the codebase with T: Sync + Send bounds, *and* make it all conditional on
222-
// `#[cfg(feature = "threads")]`. Until the multi-threading design is clarified, we'll thus leave it as is.
222+
// `#[cfg(feature = "experimental-threads")]`. Until the multi-threading design is clarified, we'll thus leave it as is.
223223
//
224224
// The following code + __static_type_check() above would make sure that InstanceStorage is Sync.
225225

godot-ffi/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ categories = ["game-engines", "graphics"]
1010
[features]
1111
custom-godot = ["godot-bindings/custom-godot"]
1212
codegen-fmt = ["godot-codegen/codegen-fmt"]
13+
experimental-godot-api = ["godot-codegen/experimental-godot-api"]
1314
trace = []
1415

1516
[dependencies]

godot/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ custom-godot = ["godot-core/custom-godot"]
1313
double-precision = ["godot-core/double-precision"]
1414
formatted = ["godot-core/codegen-fmt"]
1515
serde = ["godot-core/serde"]
16-
threads = ["godot-core/threads"]
16+
experimental-threads = ["godot-core/experimental-threads"]
17+
experimental-godot-api = ["godot-core/experimental-godot-api"]
1718

1819
# Private features, they are under no stability guarantee
1920
codegen-full = ["godot-core/codegen-full"]

godot/src/lib.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
//! As a rule of thumb, if you must use threading, prefer to use [Rust threads](https://doc.rust-lang.org/std/thread)
100100
//! over Godot threads.
101101
//!
102-
//! The Cargo feature `threads` provides experimental support for multithreading. The underlying safety
102+
//! The Cargo feature `experimental-threads` provides experimental support for multithreading. The underlying safety
103103
//! rules are still being worked out, as such you may encounter unsoundness and an unstable API.
104104
//!
105105
//! # Cargo features
@@ -135,11 +135,16 @@
135135
//! The serialized representation underlies **no stability guarantees** and may change at any time, even without a SemVer-breaking change.
136136
//! <br><br>
137137
//!
138-
//! * **`threads`**
138+
//! * **`experimental-threads`**
139139
//!
140140
//! Experimental threading support. This enables `Send`/`Sync` traits for `Gd<T>` and makes the guard types `Gd`/`GdMut` aware of
141-
//! multi-threaded references. The safety aspects of this are not ironed out yet; use at your own risk. The API may also change
142-
//! at any time.
141+
//! multi-threaded references. There safety aspects are not ironed out yet; there is a high risk of unsoundness at the moment.
142+
//! As this evolves, it is very likely that the API becomes more strict.
143+
//!
144+
//! * **`experimental-godot-api`**
145+
//!
146+
//! Access to `godot::engine` APIs that Godot marks "experimental". These are under heavy development and may change at any time.
147+
//! If you opt in to this feature, expect breaking changes at compile and runtime.
143148
//!
144149
//! # Public API
145150
//!

0 commit comments

Comments
 (0)