-
Notifications
You must be signed in to change notification settings - Fork 190
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
Change push_next()
to unsafe fn extend()
and add push()
alternative
#909
Conversation
d255d28
to
0ddf2d2
Compare
0ddf2d2
to
e567485
Compare
push_next()
as unsafe
and add push_next_one()
alternativepush_next()
as unsafe
and add push_one()
alternative
Rebased and marked as ready for review, since we're now accepting breaking changes in light of other required breaking changes for
|
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.
LGTM semantically. I don't love either name, TBH. push_one
feels like a weirdly verbose synonym of bare push
, and both feel a bit obscure. extend
might be apt for adding an extension struct, except Vec::extend
inserts multiple items, so that's differently confusing.
Do we have any evidence that everyone's ever used the multi-item function of push_next
on purpose? Asserting against that might not be the end of the world, though I guess it could be a really unpleasant surprise if someone supports environments they don't often test...
I guess I hate plain push
the least, if we need a new name. Being more concise is a decent consolation prize for the churn.
Good one! I forgot to mention, though recall that I originally used Of course, if we stick with On the other hand, since One final drawback: at that point
Are you suggesting to change With this PR as written, users will either notice the change in the changelog, have to wrap
Summarizing all the above, perhaps it is worth renaming tl;dr:
|
That's my thinking, yeah. Risk of collision with future setters seems low.
Right, changing the existing behavior avoids the trouble of having to come up with a new name, but at some difficult-to-quantify risk of runtime surprises downstream.
That sounds like a great outcome to me. We end up with exactly the Rust container idioms, improved concision all around, and no breakage risk. We could even keep |
I might have still added
While that could smooth out the transition, it might be too much of a burden to keep this as generated code in the codebase until the next breaking release, given that we're already planning to do a breaking release now. |
Also, given Pushed it regardless, LMKWYT. |
e567485
to
7279ced
Compare
a638c3e
to
0e5588c
Compare
push_next()
as unsafe
and add push_one()
alternativepush_next()
to unsafe fn extend()
and add push()
alternative
push_next()
to unsafe fn extend()
and add push()
alternativepush_next()
to unsafe fn extend()
and add push()
alternative
0e5588c
to
aaf8a26
Compare
next_base.p_next = self.p_next as _; | ||
self.p_next = <*mut T>::cast(next); |
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.
These casts are somewhat annoying and misleading, with the main problem highlighted in #970:
We treat every next
as a BaseOutStructure
, even if we should "technically" only be adding BaseOutStructure
s to p_next: *mut c_void
and BaseInStructure
s to p_next: *const c_void
. At that point the cast only exists to change the type.
…tive `push_next()` is totally `unsafe` because of dereferencing a chain of `p_next` pointers to find the end of the chain to insert, which was obfuscated by a large `unsafe` block for the `BaseOutStructure` pointer cast in commit c8c8f69 ("`next` can contain a pointer chain and we need to correct insert it."). While this function should definitely be marked unsafe, wrapping builders in `unsafe {}` en masse in user code isn't all too desirable, especially when this soundness issue only exists to optionally walk a `p_next` chain while most users are likely inserting bare structs without pointer chains most of the time. `push()` is introduced for this reason, remaining safe to call without any unintended raw pointer dereferences. `push_next()` has been renamed to `extend()` to more closely align with standard naming, and force existing users to notice this change and hopefully analyze their uses to decide which are safe/correct to switch over to safe `push()`.
aaf8a26
to
77d0f58
Compare
@Ralith also added some extra safety docs explaining writing to the pointer chain in |
LGTM. |
Fixes #905
push_next()
is totallyunsafe
because of dereferencing a chain ofp_next
pointers to find the end of the chain to insert, which was obfuscated by a largeunsafe
block for theBaseOutStructure
pointer cast in commit c8c8f69 ("next
can contain a pointer chain and we need to correct insert it.").While this function should definitely be marked unsafe, wrapping builders in
unsafe {}
en masse in user code isn't all too desirable, especially when this soundness issue only exists to optionally walk ap_next
chain while most users are likely inserting bare structs without pointer chains most of the time.push()
is introduced for this reason, remaining safe to call without any unintended raw pointer dereferences.push_next()
has been renamed toextend()
to more closely align with standard naming, and force existing users to notice this change and hopefully analyze their uses to decide which are safe/correct to switch over to safepush()
.