-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
refactor NonZero, Shared, and Unique APIs #41064
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
CC @eddyb who brought up the Deref issue. |
// the contract anyway. | ||
// This allows the null check to be elided in the destructor if we | ||
// manipulated the reference count in the same function. | ||
assume(!(*(&self.ptr as *const _ as *const *const ())).is_null()); |
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: I removed these assumes because they should be implied from NonZero, and the point of these changes is to make that metadata propagate more readily. Should probably try to validate that somehow? Not sure the best way forward.
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 think you can test this out by taking a look at the IR for:
fn foo(r: &Rc<i32>) {
drop(r.clone());
}
Ideally that's a noop function.
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.
You may need to copy it to NonZero::get
(if you can), at least until we have it in the compiler.
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'm a bit concerned that copying an assume to NonZero::get
will be disastrous to compile times (as this will show up in all accesses to every collection). Have those bloat problems with assume been resolved?
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.
|
Oh I also made Unique Copy/Clone, because it's unclear what value move semantics has here. |
This is kind of a weak argument, but copying or cloning seems contrary to the name "unique" or the docs "indicates that the possessor of this wrapper owns the referent". And is this useful? Something that contains |
Primary motivation for Copyable Unique was to have a by-value getter and maybe tax the optimizer a tiny bit less. Also to make it more of a drop-in-replacement for *mut; possibly if you're just trying to use it as an optimizer hint? I'm not particularly passionate about it either way. Maybe @nikomatsakis can speak to aliasing model implications? |
I appreciate not stressing the optimizer, but doing that does make for an annoying footgun. |
Every Unique lives in a struct that owns it, so I don't know what the footgun could possibly be; especially since using the Unique requires you to immediately turn it into a primitive pointer that can be copied. |
It's been a while, but I vaguely recall using "raw" Uniques not inside some other struct as a last-ditch attempt to prevent unwanted aliasing. Even if the wrapped struct case, there is still code working with the wrapper. |
src/libcore/ptr.rs
Outdated
pub fn ptr(self) -> *mut T { | ||
self.pointer.get() as *mut _ | ||
} | ||
|
||
/// Dereferences the content. | ||
pub unsafe fn get(&self) -> &T { |
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 think we may call this get_ref
nowadays?
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.
How do you feel about ref and ref_mut?
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.
ref
is a keyword
These are so low-level I'm ok with adding |
☔ The latest upstream changes (presumably #41098) made this pull request unmergeable. Please resolve the merge conflicts. |
src/libcore/ptr.rs
Outdated
&*self.ptr() | ||
} | ||
|
||
/// Mutably dereferences the content. |
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.
Should this be on Shared
at all? I'd expect interior mutability to be required - or I suppose we could just have something along the lines "you shouldn't ever use this unless there is no other reference around" in the documentation (e.g. Rc
with a refcount of 1
).
That's a breaking change AFAIK, I think it's for variance. |
@eddyb it still contains a Shared has, basically, no semantics other than "it's non-null" and "it doesn't have It's possible there's interesting aliasing rules to document here, but until someone figures out what Rust's aliasing rules are, that's simply impossible. |
@gankro Ahh, okay, keeping The refcounts are |
I can't speak to it with certainty, except to say that I think there is pretty broad consensus that errors ought to be mostly about which pointers get dereferenced and when, not which get copied from place to place. |
Ping to keep this on your radar @gankro! |
I'm not sure this is really blocked on me. The only real requested change is from @alexcrichton, but really the blocker is on libs/lang team people agreeing on the design. |
Another API question that I kinda spaced out on: the current design does |
@gankro Oh I thought it should be in your court because there are merge conflicts and test failures. Are you waiting on approval from libs/lang on the design before fixing those? |
Yeah |
I'll cc @rust-lang/libs to see if anyone else would like to leave a comment, but typically if we're not stabilizing something we don't discuss PRs during triage (as it's just too much to process). I would be comfortable r+'ing w/ my minor comment and a rebase. |
refactor NonZero, Shared, and Unique APIs Major difference is that I removed Deref impls, as apparently LLVM has trouble maintaining metadata with a `&ptr -> &ptr` API. This was cited as a blocker for ever stabilizing this API. It wasn't that ergonomic anyway. * Added `get` to NonZero to replace Deref impl * Added `ptr` getter to Shared/Unique to replace Deref impl * Added Unique's `get` and `get_mut` conveniences to Shared * Deprecated `as_mut_ptr` on Shared in favour of `ptr` Note that Shared used to primarily expose only `*const` but there isn't a good justification for that, so I made it `*mut`.
⌛ Testing commit e8234e0 with merge 42a4f37... |
I believe the documentation needs updated to no longer refer to |
API changed in rust-lang/rust#41064; see also the tracking issue rust-lang/rust#27730 for more information.
Changed in rust-lang/rust#41064 Fixes Manishearth#55
Changed in rust-lang/rust#41064 Fixes Manishearth#55
Changed in rust-lang/rust#41064 Fixes Manishearth#55
- New allocator API - Remove the "allocator" feature, which should be unnecessary due to how the new allocator API works - NonZero no longer implements Deref (rust-lang/rust#41064) - NonZero::new() returns an Option; use NonZero::new_unchecked() - Thread locals are no longer 'static (rust-lang/rust#43746) - Changes to feature flags - Use unsafe to access extern static (rust-lang/rust#36247)
Major difference is that I removed Deref impls, as apparently LLVM has
trouble maintaining metadata with a
&ptr -> &ptr
API. This was citedas a blocker for ever stabilizing this API. It wasn't that ergonomic
anyway.
get
to NonZero to replace Deref implptr
getter to Shared/Unique to replace Deref implget
andget_mut
conveniences to Sharedas_mut_ptr
on Shared in favour ofptr
Note that Shared used to primarily expose only
*const
but there isn'ta good justification for that, so I made it
*mut
.