@@ -62,13 +62,25 @@ pub(super) mod private {
62
62
63
63
/// Library-implemented trait to check bounds on `GodotClass` types.
64
64
///
65
- /// See also [`bounds`](crate::obj::bounds) module documentation.
65
+ /// See [`bounds`](crate::obj::bounds) module for how to use this for bounds checking.
66
+ ///
67
+ /// <div class="warning">
68
+ /// <strong>Never</strong> implement this trait manually.
69
+ /// </div>
70
+ ///
71
+ /// Most of the time, this trait is covered by [`#[derive(GodotClass)`](../bind/derive.GodotClass.html).
72
+ /// If you implement `GodotClass` manually, use the [`implement_godot_bounds!`][crate::implement_godot_bounds] macro.
73
+ ///
74
+ /// There are two reasons to avoid a hand-written `impl Bounds`:
75
+ /// - The trait is `unsafe` and it is very easy to get internal bounds wrong. This will lead to immediate UB.
76
+ /// - Apart from the documented members, the trait may have undocumented items that may be broken at any time and stand under no SemVer
77
+ /// guarantees.
66
78
///
67
79
/// # Safety
68
80
///
69
- /// Internal.
70
- /// You **must not** implement this trait yourself. [`#[derive(GodotClass)`](../bind/derive.GodotClass.html) will automatically do it.
81
+ /// Internal. The library implements this trait and ensures safety.
71
82
pub unsafe trait Bounds {
83
+ /// Defines the memory strategy of the static type.
72
84
type Memory : Memory ;
73
85
74
86
/// Defines the memory strategy of the instance (at runtime).
@@ -79,9 +91,50 @@ pub(super) mod private {
79
91
type Declarer : Declarer ;
80
92
}
81
93
94
+ /// Implements [`Bounds`] for a user-defined class.
95
+ ///
96
+ /// This is only necessary if you do not use the proc-macro API.
97
+ ///
98
+ /// Since `Bounds` is a supertrait of [`GodotClass`][crate::obj::GodotClass], you cannot accidentally forget to implement it.
99
+ ///
100
+ /// # Example
101
+ /// ```no_run
102
+ /// use godot::prelude::*;
103
+ /// use godot::obj::bounds::implement_godot_bounds;
104
+ /// use godot::builtin::meta::ClassName;
105
+ ///
106
+ /// struct MyClass {}
107
+ ///
108
+ /// impl GodotClass for MyClass {
109
+ /// type Base = Node;
110
+ ///
111
+ /// # const INIT_LEVEL: Option<InitLevel> = None;
112
+ /// fn class_name() -> ClassName {
113
+ /// ClassName::from_ascii_cstr(b"MyClass\0")
114
+ /// }
115
+ /// }
116
+ ///
117
+ /// implement_godot_bounds!(MyClass);
118
+ #[ macro_export]
119
+ macro_rules! implement_godot_bounds {
120
+ ( $UserClass: ty) => {
121
+ // SAFETY: bounds are library-defined, dependent on base. User has no influence in selecting them -> macro is safe.
122
+ unsafe impl $crate:: obj:: Bounds for $UserClass {
123
+ type Memory = <<$UserClass as $crate:: obj:: GodotClass >:: Base as $crate:: obj:: Bounds >:: Memory ;
124
+ type DynMemory = <<$UserClass as $crate:: obj:: GodotClass >:: Base as $crate:: obj:: Bounds >:: DynMemory ;
125
+ type Declarer = $crate:: obj:: bounds:: DeclUser ;
126
+ }
127
+ } ;
128
+ }
129
+
82
130
pub trait Sealed { }
83
131
}
84
132
133
+ // ----------------------------------------------------------------------------------------------------------------------------------------------
134
+ // Macro re-exports
135
+
136
+ pub use crate :: implement_godot_bounds;
137
+
85
138
// ----------------------------------------------------------------------------------------------------------------------------------------------
86
139
// Memory bounds
87
140
0 commit comments