README: Add lifetime-preserving builder example using slice::from_ref (#381)

It isn't too uncommon to pass a single builder element into another
builder, and `slice::from_ref` fits perfectly while preserving lifetime
of the builder without calling `.build()`. We have used this
successfully in our codebase to uncover and prevent numerous
use-after-free bugs, and thought it's worth to share on the front page.
This commit is contained in:
Marijn Suijten 2021-03-02 18:22:04 +01:00 committed by GitHub
parent 00e7bbd8f3
commit eb75ded793
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -78,7 +78,7 @@ let queue_info = [vk::DeviceQueueCreateInfo::builder()
.queue_priorities(&priorities)
.build()];
// We don't need to call build here because builders implement `Deref`.
// We don't need to call `.build()` here because builders implement `Deref`.
let device_create_info = vk::DeviceCreateInfo::builder()
.queue_create_infos(&queue_info)
.enabled_extension_names(&device_extension_names_raw)
@ -89,6 +89,18 @@ let device: Device = instance
.unwrap();
```
To not lose this lifetime single items can be "cast" to a slice of length _one_ with `std::slice::from_ref` while still taking advantage of `Deref`:
```rust
let queue_info = vk::DeviceQueueCreateInfo::builder()
.queue_family_index(queue_family_index)
.queue_priorities(&priorities);
let device_create_info = vk::DeviceCreateInfo::builder()
.queue_create_infos(std::slice::from_ref(&queue_info))
...;
```
Builders have an explicit lifetime, and are marked as `#[repr(transparent)]`.
```rust
#[repr(transparent)]