Why Is It Designed This Way?
Why does Gd<T> exist instead of Box<T>?
Godot owns object identity and may use manual or reference-counted memory.
Gd<T> is a typed view of an engine object pointer whose clone/drop behavior
follows the class’s memory strategy. A Rust box would falsely claim sole
allocation and destruction authority.
Why are Rust user classes dynamically borrowed?
Godot and GDScript can re-enter Rust through signals and virtual callbacks.
Compile-time lifetimes cannot describe all foreign call sequences. bind and
bind_mut therefore return guards enforcing shared/exclusive access at runtime,
similar to RefCell but attached to engine object storage.
Why macros and code generation?
Godot publishes a large versioned API description. Generated engine classes and procedural macros keep function signatures, inheritance markers, registration, argument conversion, and virtual trampolines synchronized. Handwritten wrappers would multiply unsafe boilerplate and drift.
Why is inheritance represented with traits and composition?
Rust has no class inheritance. GodotClass::Base, Inherits<T>, generated
deref behavior, and a stored Base<T> preserve the useful relationships while
keeping the Rust user value structurally explicit.
Why are most objects main-thread-bound?
Godot’s scene tree and object lifecycle are not generally thread-safe. The safe
API refuses to mark Gd<T> freely Send/Sync. Reviewed value operations and
explicit thread-safe callables opt in separately.
Why catch panics at callbacks?
Rust unwinding across an extern "C" boundary is invalid. Trampolines catch and
report panics, clean task/callback state, and return through the engine ABI.