-
Notifications
You must be signed in to change notification settings - Fork 267
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
Adjust Vec to build on stable Rust #223
Conversation
FYI, after finishing the changes, I made a pass through the chapter and tested the cumulative code at each step, confirming that it compiles successfully on stable Rust. |
I want to register interest in getting this PR rebased and merged. |
I wouldn't mind rebasing and making the needed changes to get this ready again; could we get a reviewer/assignee first so we can know if the maintainers are interested in getting it merged? @JohnTitor, would you be interested in reviewing, or helping us find someone? |
Hey sorry for the delay! I'll try to find some time to review in a few days and it'd be great if you could rebase meanwhile. |
@JohnTitor I resolved the conflicts and rebased, so it should be ready for review whenever you're able! |
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.
Sorry for the delay! Just read and the implementation itself looks good to me, just left suggestions for the style issues.
Co-authored-by: Yuki Okushi <jtitor@2k36.org>
Thanks, I applied all the suggested changes. |
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! But I'm going to ask the libs team to review since this is a major change and I'm not sure if I've got the whole picture correctly (related Zulip topic: https://rust-lang.zulipchat.com/#narrow/stream/219381-t-libs/topic/review.20request.20for.20the.20nomicon.20PR), I'll wait for a week or so to get some more eyes. Sorry to keep you waiting.
@@ -7,20 +7,17 @@ ask Rust if `T` `needs_drop` and omit the calls to `pop`. However in practice | |||
LLVM is *really* good at removing simple side-effect free code like this, so I | |||
wouldn't bother unless you notice it's not being stripped (in this case it is). |
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.
Note that the above is only true if LLVM can prove that the loop is finite. This is true in the case of Vec
, but for example LLVM has no way to know that a linked list has no cycles.
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.
Makes sense. And based on the docs for needs_drop it sounds like even in the Vec
case LLVM might not eliminate the loop in debug builds. In any case, it is probably fragile to rely on LLVM for this behavior. I'm thinking of a few options for how we could address this:
- Leave the code as is, but change the text to make the risk more clear.
- Use a
mem::needs_drop
to skip the loop ifT
is!Drop
. - Instead of an explicit loop, use
ptr::drop_in_place
(which is what the standard libraryVec
does). - Start with the current code, but within the section discuss its pitfalls and iterate on it, progressing to 2 and/or 3.
I would lean toward option 4, since currently this section is very short and could benefit from more discussion and examples to illustrate the usage of mem::needs_drop
and ptr::drop_in_place
. If we go with 2, 3, or 4, it will also require changes to vec-raw.md
and vec-final.md
for consistency. If you don't mind, do you think I could create a separate PR for this change, since it addresses a separate issue from the current PR?
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 agree that option 4 sounds like the best way to go. It's fine to do this in a separate PR.
if self.len == self.cap() { self.buf.grow(); } | ||
if self.len == self.cap() { | ||
self.buf.grow(); | ||
} | ||
|
||
unsafe { | ||
ptr::write(self.ptr().offset(self.len as isize), elem); |
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.
All the calls to .offset
can be replaced with .add
which avoids the need to cast to isize
.
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.
Nice! There are a couple dozen or so places throughout the chapter where this change could be made. Would you mind if I create a separate PR for this?
Next we need to figure out what to actually do when we *do* want space. For that, | ||
we use the global allocation functions [`alloc`][alloc], [`realloc`][realloc], | ||
and [`dealloc`][dealloc] which are available in stable Rust in | ||
[`std::alloc`][std_alloc]. These functions are expected to become deprecated in | ||
favor of the methods of [`std::alloc::Global`][Global] after this type is stabilized. |
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.
At some point I really want to implement rust-lang/rust#77974.
It's been two weeks, @blkerby could you address Amanieu's reviews? Once it's done, I'm going to merge this finally. |
@JohnTitor I think the reviews are identifying additional ways to improve the Vec chapter that are orthogonal to the changes in this PR. If you think it makes sense, could we merge this one and then tackle those in separate PRs? |
Works for me, I'd also open another PR. Thanks for your awesome work, @blkerby! |
hey, thanks a lot!! |
Update books ## nomicon 4 commits in 8551afbb2ca6f5ea37fe58380318b209785e4e02..55de6fa3c1f331774da19472c9ee57d2ae9eb039 2021-04-01 21:58:50 +0900 to 2021-05-12 00:31:01 +0900 - Clarify some of the language around marking traits safe/unsafe. (rust-lang/nomicon#268) - Use pointer 'add' instead of 'offset' (rust-lang/nomicon#265) - Adjust Vec to build on stable Rust (rust-lang/nomicon#223) - Update link to c++ atomic ordering docs (rust-lang/nomicon#264) ## reference 3 commits in d23f9da8469617e6c81121d9fd123443df70595d..5aa457bf1b54bd2cd5d4cf49797f29299bdf89a7 2021-04-28 11:16:44 -0700 to 2021-05-05 08:39:22 -0700 - Explicitly state result of compound assignment (rust-lang/reference#1013) - Adjust the definition of `target_family` (rust-lang/reference#1006) - Fix typo in `Traits` (rust-lang/reference#1012) ## book 2 commits in 50dd06cb71beb27fdc0eebade5509cdcc1f821ed..55a26488ddefc8433e73a2e8352d70f7a5c7fc2b 2021-04-23 13:21:54 -0500 to 2021-05-09 12:03:18 -0500 - Past-tensify "lead" -> "led" (rust-lang/book#2717) - Merge pull request rust-lang/book#2718 from rust-lang/update-rustc ## rust-by-example 2 commits in e0a721f5202e6d9bec0aff99f10e44480c0da9e7..5f8c6da200ada77760a2fe1096938ef58151c9a6 2021-04-27 09:32:15 -0300 to 2021-04-29 08:08:01 -0300 - Fix Typo in LRBE section; closes rust-lang/rust-by-example#1434 (rust-lang/rust-by-example#1437) - Add some tests to cargo/test.md. Partially addresses rust-lang/rust-by-example#1304 (rust-lang/rust-by-example#1438) ## rustc-dev-guide 3 commits in e72b43a64925ce053dc7830e21c1a57ba00499bd..1e6c7fbda4c45e85adf63ff3f82fa9c870b1447f 2021-04-27 12:35:37 -0700 to 2021-05-10 13:38:24 +0900 - Unified CPU Requirements (rust-lang/rustc-dev-guide#1126) - add 'waiting-for-review' incantation to main contrib page (rust-lang/rustc-dev-guide#1124) - Link to Zulip search for finding the most recent check-in (rust-lang/rustc-dev-guide#1118)
Hi, first time contributing to the Nomicon here. I'm aware this is a somewhat large proposed change (larger than I anticipated it being when I began) but I hope it will be useful.
The chapter on implementing Vec was written to build on nightly Rust. From the discussion in 9.1 (Layout), the primary motivation for this was to get an optimized non-nullable pointer type. Since
std::ptr::NonNull
is now stable, this can achieved on stable Rust. This pull request makes the changes throughout the chapter necessary to implement Vec usingstd::ptr::NonNull
instead of the unstableUnique
.Currently much of the code in the main body of the chapter does not compile on the latest nightly Rust because it relies on unstable APIs which have changed (for instance,
std::alloc::oom
,alloc::heap::{allocate, reallocate, deallocate}
are gone, andUnique
no longer implementsDeref
). The final code in the last section of the chapter compiles, because it has been updated to use current unstable APIs such asstd::alloc::Global
. This pull request updates the main body of the chapter as well as the final code so that they are consistent with each other, both now using the stable allocation functions instd::alloc
(while mentioning the new unstable typestd::alloc::Global
in the text).Instead of incorporating
NonNull
directly intoVec
,RawVec
, etc. as this pull request does, one alternative would be to implement a stable version ofUnique
usingNonNull
internally, and then include thisUnique
inVec
,RawVec
, etc. I briefly started going down that pathway before concluding that for this to be convenient quite a few methods would need to be implemented for this newUnique
, which would seem to create a distraction from the main goal and add an unnecessary layer of abstraction. But this would be another option if there's a preference for going that way.Fixes #5, fixes #70, fixes #83, fixes #160