-
Notifications
You must be signed in to change notification settings - Fork 213
Decouple next lifetime from itself in TaggedStructure::push() and ::extend()
#1005
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Ralith
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can't think of any reason why this would be wrong, though I'm not super great at reasoning about variance.
|
This manually-reimplemented lifetime/borrow-checking surrounding a bunch of raw pointers is tricky and finicky to get right, that's exactly why we have a bunch of tests around it to ensure expected correctness as well as usability. As part of this change I'd appreciate to see an additional test that demonstrates what currently isn't supported (I can vaguely assume), and so that this doesn't regress in the future. Also, welcome back ;) |
8b39640 to
b6b7fd7
Compare
|
That's a fair request. You don't need an additional test because the existing test would cover this case with minor modifications. I just had to make
I'm totally new here 😅 |
|
Thanks for the test. I agree that this case should work, and I confirm that it fails without this change. There is at least one subtlety here: However, I think that's okay: if tl;dr I'm reasonably confident this change is correct and desirable. |
|
As an example, I ran into this using the VideoCapabilitiesKHR, VideoDecodeCapabilitiesKHR pointer chain. I cannot access the decode capabilities because the lifetime of |
|
Thanks for taking the time to demonstrate this in a test, which matches what I expected to have been broken. I did however specifically request an additional test because the existing ones are quite convoluted without documentation on the expected behaviour, something which I've started rectifying when adding trybuild failures. The one you modified merely concerns itself with pointer values and wasn't intended to test lifetimes, for which I believe we should instead copy and modify the trybuild failure into a working test together with explanatory comments. Together, they can be easily compared to understand why one is designed to compile while the other is not. I've pushed the result of that to
Your previous account could already be used here on the @Ralith I concur that those "nested" pointer chains remain and may be ugly, though not exploitable with them being raw pointers and possible traversal ( |
ash/src/vk.rs
Outdated
| } | ||
| let _ = variable_pointers; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is now moved to a different test with adequate explanation (not let _ =... 😉) and to not clobber this pointer-check test, we can remove it when rebasing on master.
next lifetime from self in TaggedStructure::push() and ::extend()
MarijnS95
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot, I've rebased this to make it compatible with master and demonstrate that your suggestion fixes the test as described, as well as extended the title/description to explain what this is fixing and how.
Not yet sure how to better describe that next is still borrowed for the lifetime of 'a though while the contents of next via TaggedStructure<'b> are now decoupled instead; will need some more tuning of the wording.
next lifetime from self in TaggedStructure::push() and ::extend()next lifetime from itself in TaggedStructure::push() and ::extend()
|
Specifically, if we look at the failing test: having |
… `::extend()` Right now `TaggedStructure::push()` is defined by ash-rs#994 as: ```rs fn push<T: Extends<Self> + 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.
Ralith
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will need some more tuning of the wording.
Which wording, specifically? The comments in the vicinity of the change still seem correct to me.
That in the PR description and commit body, which was originally missing until I typed something up. Specifically, the issue doesn't seem to be related to |
|
Commit text LGTM, and I don't think it merits going over with a super fine toothed comb because it's descriptive and not part of our public docs. |
|
I just prefer my contributions (including descriptions of complex lifetime changes) to be reviewed as much as I review any other change. Thanks for confirming, and merging now to unblock CI. |

Right now
TaggedStructure::push()is defined by #994 as:This requires that the extending structure
nexthas the same lifetime as the contents of the base structureself: TaggedStructure<'a>because ofnext: &'a mut T, andnextitself because ofT: TaggedStructure<'a>which is unnecessarily restricting. Specifically, even afterselfis no longer live (i.e. it is no longer mutably borrowingnext)nextcannot be accessed because it is mutably borrowed within itself through the fixed/shared lifetime of'aas demonstrated by a new test in commit 4942dc3. The same restriction exists forTaggedStructure::extend().This PR decouples lifetime
'afor the contents ofselfand the borrow ofnextfrom a new lifetime'bfor the contents ofnextinpush()andextend()to require that the contents ofnextoutlive the borrow ofnextrather than consideringnextto remain mutably borrowed within itself.