-
Notifications
You must be signed in to change notification settings - Fork 213
Description
We removed builder structs, together with the .build() footgun and moving their lifetimes to the underlying repr(C) struct in #602. This goes somewhat against the design of -sys crates which ash was anyway ahead of, and is in this funny spot where it provides both low-level representations as well as high-level hand-holds within the same crate and on the same types.
On many FFI crates that I've been generating lately we want to use our repr(C) structures in generated FFI bindings from bindgen using allowlist/blocklist rather than letting it generate completely unusable Vulkan FFI types for us (that are incompatible and require transmutes):
use ash::vk::{SubmitInfo as VkSubmitInfo};
// include!("bindings.rs");
extern "C" {
pub fn SomethingExternal(..., submits: *const VkSubmitInfo) -> ...;
}Which will fail to compile because of the missing lifetime on VkSubmitInfo. There is a workaround however, but it doesn't seem ideal:
type VkSubmitInfo = ash::vk::SubmitInfo<'static>;
// include!("bindings.rs");
extern "C" {
pub fn SomethingExternal(..., submits: *const VkSubmitInfo) -> ...;
}This requires transmuting the lifetime away into 'static if this struct is borrowing something on the heap, which is true for VkSubmitInfo as it references a bunch of slices.
As for a solution, I'm not sure if we should be reintroducing builders because of this. Or something else entirely, while keeping a .build() much better hidden/guarded by for example requiring all high-level Ash functions to take a high-level lifetimed structure?
If we perform such a type split again however, it paves the way for proper ash-sys separation. Additionally we've discussed borrows (for non-DSTs) being ABI compatible with raw pointers, such that we could even generate structs twice with borrows on (most) fields to allow the user to use regular FRU instead of the builder pattern; all while having a zero-copy (unsafe) transmute into the FFI type-struct.