Skip to content

Commit e6f6d95

Browse files
committed
Remove one instance of library UB from Array
Add the ability to add unsafe + safety docs to arbitrary methods through codegen More accurately track the safety invariant of `Array`: - Make all methods of `InnerArray` that return `VariantArray` unsafe - Make `Array::as_inner()` unsafe - Add `Array::as_inner_ref()` to allow safe usage of immutable methods - Reword some safety docs
1 parent af0f02b commit e6f6d95

File tree

6 files changed

+172
-63
lines changed

6 files changed

+172
-63
lines changed

godot-codegen/src/generator/builtins.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,21 @@ fn make_special_builtin_methods(class_name: &TyName, _ctx: &Context) -> TokenStr
163163
}
164164
}
165165

166+
/// Get the safety docs of a method if it should be unsafe
167+
fn method_safety_doc(class_name: &TyName, method: &BuiltinMethod) -> Option<TokenStream> {
168+
if class_name.godot_ty == "Array" {
169+
if &method.return_value().type_tokens().to_string() == "VariantArray" {
170+
return Some(quote! {
171+
#[doc = "# Safety"]
172+
#[doc = ""]
173+
#[doc = "You must ensure that the returned array fulfils the safety invariants of [`Array`](crate::builtin::Array)"]
174+
});
175+
}
176+
}
177+
178+
None
179+
}
180+
166181
fn make_builtin_method_definition(
167182
builtin_class: &BuiltinClass,
168183
method: &BuiltinMethod,
@@ -220,12 +235,15 @@ fn make_builtin_method_definition(
220235
)*/
221236
};
222237

238+
let safety_doc = method_safety_doc(builtin_class.name(), method);
239+
223240
functions_common::make_function_definition(
224241
method,
225242
&FnCode {
226243
receiver,
227244
varcall_invocation,
228245
ptrcall_invocation,
229246
},
247+
safety_doc,
230248
)
231249
}

godot-codegen/src/generator/classes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,5 +469,6 @@ fn make_class_method_definition(
469469
varcall_invocation,
470470
ptrcall_invocation,
471471
},
472+
None,
472473
)
473474
}

godot-codegen/src/generator/functions_common.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,11 @@ impl FnDefinitions {
8282
}
8383
}
8484

85-
pub fn make_function_definition(sig: &dyn Function, code: &FnCode) -> FnDefinition {
85+
pub fn make_function_definition(
86+
sig: &dyn Function,
87+
code: &FnCode,
88+
safety_doc: Option<TokenStream>,
89+
) -> FnDefinition {
8690
let has_default_params = default_parameters::function_uses_default_params(sig);
8791
let vis = if has_default_params {
8892
// Public API mapped by separate function.
@@ -92,7 +96,9 @@ pub fn make_function_definition(sig: &dyn Function, code: &FnCode) -> FnDefiniti
9296
make_vis(sig.is_private())
9397
};
9498

95-
let (maybe_unsafe, safety_doc) = if function_uses_pointers(sig) {
99+
let (maybe_unsafe, safety_doc) = if let Some(safety_doc) = safety_doc {
100+
(quote! { unsafe }, safety_doc)
101+
} else if function_uses_pointers(sig) {
96102
(
97103
quote! { unsafe },
98104
quote! {

godot-codegen/src/generator/utility_functions.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ pub(crate) fn make_utility_function_definition(function: &UtilityFunction) -> To
7878
varcall_invocation,
7979
ptrcall_invocation,
8080
},
81+
None,
8182
);
8283

8384
// Utility functions have no builders.

godot-codegen/src/generator/virtual_traits.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ fn make_virtual_method(method: &ClassMethod) -> Option<TokenStream> {
124124
varcall_invocation: TokenStream::new(),
125125
ptrcall_invocation: TokenStream::new(),
126126
},
127+
None,
127128
);
128129

129130
// Virtual methods have no builders.

0 commit comments

Comments
 (0)