Skip to content

Lifetime expansion when infos reference other data in builders #395

@Oliver-makes-code

Description

@Oliver-makes-code
let window = Arc::new(event_loop.create_window(Window::default_attributes())?);

let version = vk::make_version(ENGINE_VERSION.0, ENGINE_VERSION.1, ENGINE_VERSION.2);

let info = {
    let application_info = vk::ApplicationInfo::builder() // <-- Lifetime 'a start
        .engine_name(ENGINE_NAME_BYTES)
        .engine_version(version)
        .application_name(GAME_NAME_BYTES)
        .application_version(version)
        .api_version(vk::make_version(1, 4, 0))
        .build();

    let extensions = vulkanalia::window::get_required_instance_extensions(&window) // <-- Lifetime 'b start
        .iter()
        .map(|e| e.as_ptr())
        .collect::<Vec<_>>();

    let info = vk::InstanceCreateInfo::builder() // <-- Lifetime 'c start
        .application_info(&application_info)
        .enabled_extension_names(&extensions)
        .build(); // <-- build() discards lifetime information

    info // Lifetime 'c passed to upper `info`, lifetime 'a, and 'b end, but since the lifetime information was discarded, Rust lets this happens
};

This is because your InstanceCreateInfo doesn't reference any lifetimes for the objects it references

#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub struct InstanceCreateInfo {
    pub s_type: StructureType,
    pub next: *const c_void,
    pub flags: InstanceCreateFlags,
    pub application_info: *const ApplicationInfo, // <-- Pointer to direct ApplicationInfo, not a reference, so lifetime is not preserved
    pub enabled_layer_count: u32,
    pub enabled_layer_names: *const *const c_char,
    pub enabled_extension_count: u32,
    pub enabled_extension_names: *const *const c_char, // <-- Same here
}

It can be fixed by doing this, to mark that the create info depends on the lifetime of another object

#[repr(C)]
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub struct InstanceCreateInfo<'a> {
    pub s_type: StructureType,
    pub next: *const c_void,
    pub flags: InstanceCreateFlags,
    pub application_info: *const ApplicationInfo,
    pub enabled_layer_count: u32,
    pub enabled_layer_names: *const *const c_char,
    pub enabled_extension_count: u32,
    pub enabled_extension_names: *const *const c_char,
    pub _marker: PhantomData<&'a ()> // Phantom Data is a ZST, it will not affect the layout
}

I stumbled across this when I noticed that the info doesn't contain a lifetime, so I thought the info stored the direct objects for them, but when I went to check it didn't
This issue likely occurs with other infos, since they do the same thing

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions