Skip to content

Commit 3bffdf6

Browse files
committed
Terminology around safety/safeguard levels
Renames: - "checks" -> "safeguards" - "debug" -> "dev" (matches Cargo profile) - "paranoid" -> "strict" - "fast-unsafe" -> "disengaged"
1 parent fcf8b0f commit 3bffdf6

File tree

22 files changed

+155
-84
lines changed

22 files changed

+155
-84
lines changed

godot-bindings/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ api-custom = ["dep:bindgen", "dep:regex", "dep:which"]
3333
api-custom-json = ["dep:nanoserde", "dep:bindgen", "dep:regex", "dep:which"]
3434
api-custom-extheader = []
3535

36-
debug-checks-balanced = []
37-
release-checks-fast-unsafe = []
36+
# Safeguard levels (see godot/lib.rs for detailed documentation).
37+
safeguards-dev-balanced = []
38+
safeguards-release-disengaged = []
3839

3940
[dependencies]
4041
gdextension-api = { workspace = true }

godot-bindings/src/lib.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,22 +268,22 @@ pub fn since_api(major_minor: &str) -> bool {
268268
!before_api(major_minor)
269269
}
270270

271-
pub fn emit_checks_mode() {
272-
let check_modes = ["fast-unsafe", "balanced", "paranoid"];
273-
let mut checks_level = if cfg!(debug_assertions) { 2 } else { 1 };
271+
pub fn emit_safeguard_levels() {
272+
let safeguard_modes = ["disengaged", "balanced", "strict"];
273+
let mut safeguards_level = if cfg!(debug_assertions) { 2 } else { 1 };
274274
#[cfg(debug_assertions)]
275-
if cfg!(feature = "debug-checks-balanced") {
276-
checks_level = 1;
275+
if cfg!(feature = "safeguards-dev-balanced") {
276+
safeguards_level = 1;
277277
}
278278
#[cfg(not(debug_assertions))]
279-
if cfg!(feature = "release-checks-fast-unsafe") {
280-
checks_level = 0;
279+
if cfg!(feature = "safeguards-release-disengaged") {
280+
safeguards_level = 0;
281281
}
282282

283-
for mode in check_modes.iter() {
284-
println!(r#"cargo:rustc-check-cfg=cfg(checks_at_least, values("{mode}"))"#);
283+
for mode in safeguard_modes.iter() {
284+
println!(r#"cargo:rustc-check-cfg=cfg(safeguards_at_least, values("{mode}"))"#);
285285
}
286-
for mode in check_modes.iter().take(checks_level + 1) {
287-
println!(r#"cargo:rustc-cfg=checks_at_least="{mode}""#);
286+
for mode in safeguard_modes.iter().take(safeguards_level + 1) {
287+
println!(r#"cargo:rustc-cfg=safeguards_at_least="{mode}""#);
288288
}
289289
}

godot-codegen/src/generator/classes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ fn make_class(class: &Class, ctx: &mut Context, view: &ApiView) -> GeneratedClas
195195
fn __checked_id(&self) -> Option<crate::obj::InstanceId> {
196196
// SAFETY: only Option due to layout-compatibility with RawGd<T>; it is always Some because stored in Gd<T> which is non-null.
197197
let rtti = unsafe { self.rtti.as_ref().unwrap_unchecked() };
198-
#[cfg(checks_at_least = "paranoid")]
198+
#[cfg(safeguards_at_least = "strict")]
199199
rtti.check_type::<Self>();
200200
Some(rtti.instance_id())
201201
}

godot-codegen/src/generator/native_structures.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ fn make_native_structure_field_and_accessor(
219219

220220
let obj = #snake_field_name.upcast();
221221

222-
#[cfg(checks_at_least = "balanced")]
222+
#[cfg(safeguards_at_least = "balanced")]
223223
assert!(obj.is_instance_valid(), "provided node is dead");
224224

225225
let id = obj.instance_id().to_u64();

godot-core/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ api-4-4 = ["godot-ffi/api-4-4"]
3838
api-4-5 = ["godot-ffi/api-4-5"]
3939
# ]]
4040

41-
debug-checks-balanced = ["godot-ffi/debug-checks-balanced"]
42-
release-checks-fast-unsafe = ["godot-ffi/release-checks-fast-unsafe"]
41+
# Safeguard levels (see godot/lib.rs for detailed documentation).
42+
safeguards-dev-balanced = ["godot-ffi/safeguards-dev-balanced"]
43+
safeguards-release-disengaged = ["godot-ffi/safeguards-release-disengaged"]
4344

4445
[dependencies]
4546
godot-ffi = { path = "../godot-ffi", version = "=0.4.1" }

godot-core/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ fn main() {
1818

1919
godot_bindings::emit_godot_version_cfg();
2020
godot_bindings::emit_wasm_nothreads_cfg();
21-
godot_bindings::emit_checks_mode();
21+
godot_bindings::emit_safeguard_levels();
2222
}

godot-core/src/builtin/collections/array.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ impl<T: ArrayElement> Array<T> {
968968
}
969969

970970
/// Validates that all elements in this array can be converted to integers of type `T`.
971-
#[cfg(checks_at_least = "paranoid")]
971+
#[cfg(safeguards_at_least = "strict")]
972972
pub(crate) fn debug_validate_int_elements(&self) -> Result<(), ConvertError> {
973973
// SAFETY: every element is internally represented as Variant.
974974
let canonical_array = unsafe { self.assume_type_ref::<Variant>() };
@@ -990,7 +990,7 @@ impl<T: ArrayElement> Array<T> {
990990
}
991991

992992
// No-op in Release. Avoids O(n) conversion checks, but still panics on access.
993-
#[cfg(not(checks_at_least = "paranoid"))]
993+
#[cfg(not(safeguards_at_least = "strict"))]
994994
pub(crate) fn debug_validate_int_elements(&self) -> Result<(), ConvertError> {
995995
Ok(())
996996
}
@@ -1233,7 +1233,7 @@ impl<T: ArrayElement> Clone for Array<T> {
12331233
let copy = unsafe { self.clone_unchecked() };
12341234

12351235
// Double-check copy's runtime type in Debug mode.
1236-
if cfg!(checks_at_least = "paranoid") {
1236+
if cfg!(safeguards_at_least = "strict") {
12371237
copy.with_checked_type()
12381238
.expect("copied array should have same type as original array")
12391239
} else {

godot-core/src/classes/class_runtime.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
//! Runtime checks and inspection of Godot classes.
99
1010
use crate::builtin::{GString, StringName, Variant, VariantType};
11-
#[cfg(checks_at_least = "paranoid")]
11+
#[cfg(safeguards_at_least = "strict")]
1212
use crate::classes::{ClassDb, Object};
1313
use crate::meta::CallContext;
14-
#[cfg(checks_at_least = "paranoid")]
14+
#[cfg(safeguards_at_least = "strict")]
1515
use crate::meta::ClassId;
1616
use crate::obj::{bounds, Bounds, Gd, GodotClass, InstanceId, RawGd, Singleton};
1717
use crate::sys;
@@ -191,7 +191,7 @@ where
191191
Gd::<T>::from_obj_sys(object_ptr)
192192
}
193193

194-
#[cfg(checks_at_least = "balanced")]
194+
#[cfg(safeguards_at_least = "balanced")]
195195
pub(crate) fn ensure_object_alive(
196196
instance_id: InstanceId,
197197
old_object_ptr: sys::GDExtensionObjectPtr,
@@ -212,7 +212,7 @@ pub(crate) fn ensure_object_alive(
212212
);
213213
}
214214

215-
#[cfg(checks_at_least = "paranoid")]
215+
#[cfg(safeguards_at_least = "strict")]
216216
pub(crate) fn ensure_object_inherits(derived: ClassId, base: ClassId, instance_id: InstanceId) {
217217
if derived == base
218218
|| base == Object::class_id() // for Object base, anything inherits by definition
@@ -227,7 +227,7 @@ pub(crate) fn ensure_object_inherits(derived: ClassId, base: ClassId, instance_i
227227
)
228228
}
229229

230-
#[cfg(checks_at_least = "paranoid")]
230+
#[cfg(safeguards_at_least = "strict")]
231231
pub(crate) fn ensure_binding_not_null<T>(binding: sys::GDExtensionClassInstancePtr)
232232
where
233233
T: GodotClass + Bounds<Declarer = bounds::DeclUser>,
@@ -255,7 +255,7 @@ where
255255
// Implementation of this file
256256

257257
/// Checks if `derived` inherits from `base`, using a cache for _successful_ queries.
258-
#[cfg(checks_at_least = "paranoid")]
258+
#[cfg(safeguards_at_least = "strict")]
259259
fn is_derived_base_cached(derived: ClassId, base: ClassId) -> bool {
260260
use std::collections::HashSet;
261261

godot-core/src/init/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,12 @@ fn gdext_on_level_deinit(level: InitLevel) {
311311
/// responsible to uphold them: namely in GDScript code or other GDExtension bindings loaded by the engine.
312312
/// Violating this may cause undefined behavior, even when invoking _safe_ functions.
313313
///
314+
/// If you use the `disengaged` [safeguard level], you accept that UB becomes possible even **in safe Rust APIs**, if you use them wrong
315+
/// (e.g. accessing a destroyed object).
316+
///
314317
/// [gdextension]: attr.gdextension.html
315318
/// [safety]: https://godot-rust.github.io/book/gdext/advanced/safety.html
319+
/// [safeguard level]: ../index.html#safeguard-levels
316320
// FIXME intra-doc link
317321
#[doc(alias = "entry_symbol", alias = "entry_point")]
318322
pub unsafe trait ExtensionLibrary {
@@ -530,6 +534,18 @@ unsafe fn ensure_godot_features_compatible() {
530534

531535
out!("Check Godot precision setting...");
532536

537+
#[cfg(feature = "debug-log")] // Display safeguards level in debug log.
538+
let safeguards_level = if cfg!(safeguards_at_least = "strict") {
539+
"strict"
540+
} else if cfg!(safeguards_at_least = "balanced") {
541+
"balanced"
542+
} else if cfg!(safeguards_at_least = "disengaged") {
543+
"disengaged"
544+
} else {
545+
"unknown"
546+
};
547+
out!("Safeguards: {safeguards_level}");
548+
533549
let os_class = StringName::from("OS");
534550
let single = GString::from("single");
535551
let double = GString::from("double");

godot-core/src/meta/error/convert_error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ pub(crate) enum FromGodotError {
189189
},
190190

191191
/// Special case of `BadArrayType` where a custom int type such as `i8` cannot hold a dynamic `i64` value.
192-
#[cfg(checks_at_least = "paranoid")]
192+
#[cfg(safeguards_at_least = "strict")]
193193
BadArrayTypeInt {
194194
expected_int_type: &'static str,
195195
value: i64,
@@ -234,7 +234,7 @@ impl fmt::Display for FromGodotError {
234234

235235
write!(f, "expected array of type {exp_class}, got {act_class}")
236236
}
237-
#[cfg(checks_at_least = "paranoid")]
237+
#[cfg(safeguards_at_least = "strict")]
238238
Self::BadArrayTypeInt {
239239
expected_int_type,
240240
value,

0 commit comments

Comments
 (0)