From 703bc076f4bd149d43051582e47dbce2ec5e9ad5 Mon Sep 17 00:00:00 2001 From: SteveIntensifies Date: Tue, 12 Aug 2025 22:52:13 -0700 Subject: [PATCH] Decouple `next` lifetime from itself in `TaggedStructure::push()` and `::extend()` Right now `TaggedStructure::push()` is defined by #994 as: ```rs fn push + TaggedStructure<'a>>(mut self, next: &'a mut T) -> Self ``` This requires that the extending structure `next` has the same lifetime as the contents of the base structure `self: TaggedStructure<'a>` because of `next: &'a mut T`, _and `next` itself_ because of `T: TaggedStructure<'a>` which is unnecessarily restricting. Specifically, even after `self` is no longer live (i.e. it is no longer mutably borrowing `next`) `next` cannot be accessed because it is mutably borrowed within itself through the fixed/shared lifetime of `'a` as demonstrated by a new test in commit 4942dc3. The same restriction exists for `TaggedStructure::extend()`. This PR decouples lifetime `'a` for the contents of `self` and the borrow of `next` from a new lifetime `'b` for _the contents of `next`_ in `push()` and `extend()` to require that the _contents of `next`_ outlive the borrow of `next` rather than considering `next` to remain mutably borrowed within itself. --- ash/src/vk.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ash/src/vk.rs b/ash/src/vk.rs index 2e0767bf..7dfba657 100644 --- a/ash/src/vk.rs +++ b/ash/src/vk.rs @@ -81,7 +81,7 @@ pub unsafe trait TaggedStructure<'a>: Sized { /// # Panics /// If `next` contains a pointer chain of its own, this function will panic. Call `unsafe` /// [`Self::extend()`] to insert this chain instead. - fn push + TaggedStructure<'a>>(mut self, next: &'a mut T) -> Self { + fn push<'b: 'a, T: Extends + TaggedStructure<'b>>(mut self, next: &'a mut T) -> Self { // SAFETY: All implementers of `TaggedStructure` are required to have the `BaseOutStructure` layout let slf_base = unsafe { &mut *<*mut _>::cast::>(&mut self) }; // SAFETY: All implementers of `T: TaggedStructure` are required to have the `BaseOutStructure` layout @@ -110,7 +110,10 @@ pub unsafe trait TaggedStructure<'a>: Sized { /// /// The last struct in this chain (i.e. the one where `p_next` is `NULL`) must be writable /// memory, as its `p_next` field will be updated with the value of `self.p_next`. - unsafe fn extend + TaggedStructure<'a>>(mut self, next: &'a mut T) -> Self { + unsafe fn extend<'b: 'a, T: Extends + TaggedStructure<'b>>( + mut self, + next: &'a mut T, + ) -> Self { // `next` here can contain a pointer chain. This means that we must correctly attach he head // to the root and the tail to the rest of the chain For example: //