Skip to content

Commit 4942dc3

Browse files
committed
Add documented test for using structs after temporarily being part of a mutable pointer chain
This test is based on the trybuild failure test where the root structure is still being alive and used when one of its pointer-chain members is being accessed, violating mutable borrow rules. Note that this pattern still doesn't apply mutable borrow rules to *longer pointer chains where multiple structs* are pushed to the same *root struct*, resulting in those structs now referencing each other via `pNext` even after the root struct goes out of scope. This is implicitly handled - though not explicitly documented - by all Vulkan function calls remaining `unsafe` and by `push()` asserting that incoming structures have `pNext` set to `NULL`. Unless those structs were pushed into each other manually while preserving existing `pNext` pointers via `unsafe` `extend()`, which commonly isn't even possible for arbitrary extension structures that are not a root structure themselves (i.e. no other structure lists the extension structure in a `structextends`).
1 parent e377fb5 commit 4942dc3

File tree

3 files changed

+31
-9
lines changed

3 files changed

+31
-9
lines changed

ash/src/vk.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,25 @@ mod tests {
328328
assert_eq!(chain, chain2);
329329
}
330330

331+
#[test]
332+
fn test_use_struct_after_pointer_chain() {
333+
// The negative case of this test, where `pdev_props` stays alive by being
334+
// used at the end of this function while `api` is invalidly accessed first
335+
// (resulting in an immutable borrow while mutably borrowed error), exists in
336+
// `tests/fail/long_lived_root_struct_borrow.rs`. This test demonstrates the expected usage
337+
// pattern of dropping `pdev_props` so that `api` no longer becomes mutably borrowed and the
338+
// properties read from Vulkan can now be accessed by the caller.
339+
340+
let mut layers = vec![];
341+
let mut api =
342+
vk::PhysicalDeviceLayeredApiPropertiesListKHR::default().layered_apis(&mut layers);
343+
let _pdev_props = vk::PhysicalDeviceProperties2::default().push(&mut api);
344+
345+
// Access to either variable is allowed because `pdev_props` is no longer used
346+
dbg!(&api);
347+
dbg!(&layers);
348+
}
349+
331350
#[test]
332351
fn test_debug_flags() {
333352
assert_eq!(

ash/tests/fail/long_lived_root_struct_borrow.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use ash::vk::{self, TaggedStructure as _};
22

33
fn main() {
4+
// src/vk.rs holds a positive version of this test, demonstrating that `api` can be adequately
5+
// accessed when `pdev_props` is no longer live.
6+
47
let mut layers = vec![];
58
let mut api =
69
vk::PhysicalDeviceLayeredApiPropertiesListKHR::default().layered_apis(&mut layers);
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
error[E0502]: cannot borrow `api` as immutable because it is also borrowed as mutable
2-
--> tests/fail/long_lived_root_struct_borrow.rs:10:10
2+
--> tests/fail/long_lived_root_struct_borrow.rs:13:10
33
|
4-
7 | let pdev_props = vk::PhysicalDeviceProperties2::default().push(&mut api);
4+
10 | let pdev_props = vk::PhysicalDeviceProperties2::default().push(&mut api);
55
| -------- mutable borrow occurs here
66
...
7-
10 | dbg!(&api);
7+
13 | dbg!(&api);
88
| ^^^^ immutable borrow occurs here
99
...
10-
13 | dbg!(pdev_props); // Holds a borrow on api and layers
10+
16 | dbg!(pdev_props); // Holds a borrow on api and layers
1111
| ---------- mutable borrow later used here
1212

1313
error[E0502]: cannot borrow `layers` as immutable because it is also borrowed as mutable
14-
--> tests/fail/long_lived_root_struct_borrow.rs:11:10
14+
--> tests/fail/long_lived_root_struct_borrow.rs:14:10
1515
|
16-
6 | vk::PhysicalDeviceLayeredApiPropertiesListKHR::default().layered_apis(&mut layers);
16+
9 | vk::PhysicalDeviceLayeredApiPropertiesListKHR::default().layered_apis(&mut layers);
1717
| ----------- mutable borrow occurs here
1818
...
19-
11 | dbg!(&layers);
19+
14 | dbg!(&layers);
2020
| ^^^^^^^ immutable borrow occurs here
21-
12 |
22-
13 | dbg!(pdev_props); // Holds a borrow on api and layers
21+
15 |
22+
16 | dbg!(pdev_props); // Holds a borrow on api and layers
2323
| ---------- mutable borrow later used here

0 commit comments

Comments
 (0)