Change:
We currently have three internal types, , and , that are very useful when working with unsafe Rust code. Ultimately, the hope is to have a clear vision for semi-high-level, but unsafe programming using types like these. None of the current APIs have gone through the RFC process, and a comprehensive RFC should be written before any stabilization is done. cc
I'm not a fan of NonZero. I would like a more robust system that can hook into the things described in Unique is great, but I would like to rename it to Owned to better reflect what its actual semantics are (e.g. it's fine to have other pointers into it just like it's fine for Box). I would like to add a Shared equivalent for Rc/Arc to use. This is blocked by
I expanded this issue to cover the new type ().
CC Does Shared/Unique cover all your NonZero usecases?
I commented about this in , reposting here for visibility: The impls on these types are bad interfaces because they remove the optimizations can trigger, specifically the control-flow ones (not the layout optimizations, which are unaffected). They also allow writing where is a or a to obtain a , which might make unsafe code more confusing (you need to get at the lvalue). and wrappers such as and , should use a -like API ( and - or just , really), allowing LLVM to reason about their non-nullability.
alternatively, we could just promote these types to compiler primitives, right? Have them coerce to raw pointers or summat? This may also improve debug perf, as there's less abstraction in the way if it's really "just" a raw pointer, and not a Foo(Bar(const T)) that is accessed through two levels of methods.
I agree with comment about using a -like API for (and other types). It makes semantic sense.
The libs team decided to not move these APIs into FCP this cycle because the type is at the heart of all of them, and we're the least sure about .
(Answering with a small delay… :)) Unfortunately no. We would like to use instead of in , but we can’t at the moment because ’s field being private prevents matching on it in a pattern:
I don't know if this is the right place to comment, but I'm binding some C code and Unique appears perfect - except that it exposes the unsafe rather than that being internal - meaning that I need a further wrapper around it - since I know the C ptr in question isn't going to be freed randomly, and I know that its not null, I want to hide the unsafe entirely from further out users.
My suggestion would be to write a wrapper struct that has a as a member, and that frees the pointer in the in its impl.
N.B. from would almost surely replace this.
If we keep NonZero or something like it, I would love a safe (checked) way to construct one. Currently the single line of unsafe code in Serde is constructing a NonZero.
I'm making changes to this API in this PR
Would it make sense for to be an attribute of fields rather than a wrapper type? That would enable to use it. Currently it can’t because we have a macro that expands to an struct literal that can be used as a pattern in a expression, so all transitive fields must be public.
I would like to propose we stabilize these APIs now that my changes in have landed. They have varying levels of controversy, so here's my priority's prefs: Shared should absolutely be stabilized ASAP. I don't think it needs any more work. Unique should probably be stabilized, but doesn't really need to be, and might want some more scrutiny. Anyone who wants to use it can use Shared, because they provide the same API and there's no actual optimization benefits between the two today. They should probably also use Shared anyway to avoid running into UB that isn't even specified yet. NonZero could be stabilized, but it's always going to be a lame hack API, and I don't think it really matters (Shared does most of its work). That said I don't think NonZero will conflict with any future system that would theoretically obsolete it, so it's probably fine to stabilize it with a shrug. You can view the current APIs here: Shared: Unique: NonZero: The major change is that the impls are dead, as they confused LLVM. Now you explicitly call on NonZero, or on Shared/Unique. Shared and Unique are now exactly the same (covariant, nonzero, takes/produces mut), except for this distinction: This basically leaves Shared spec'd as " if it worked the way you wished it would". There's potentially room for something between Unique and Shared to capture the subtle aliasing semantics that Rc and Arc have, but we desperately need a type like Shared for the broader ecosystem, and it's not like we have immediate plans to add more aliasing metadata to Shared/Unique. Unique on the other hand is spec'd as having aliasing guarantees "as if" the were a , whatever we decide those aliasing guarantees are. Basically I punted on needing to spec Rust's aliasing rules by giving these two types the aliasing rules of other types. Some controversial points to note during FCP: /Unique are now Copy. This is basically an ergonomics thing, to make them as similar to as possible. It's unsafe code, we should be getting out of our users' way. I have mild concern this is sketchy for Unique with its new aliasing model, but mostly I don't think it will matter. is now covariant, even though it's "aliased and mutable". Why? Because it would literally be useless otherwise. Arc, Rc, LinkedList, and every other type that uses Shared needs covariance, and there's no way to "undo" invariance. Yes this is a foot gun. No I don't think it's a big deal (it's almost always right -- literally always right for the stdlib). Shared's documentation highlights the issue. /Unique don't require/guarantee alignment when they dangle. This means enums potentially miss out on Even More Tagging Optimizations. However it means that users can do their own by-hand tagging optimizations. For instance HashMap does this today. briefly mused on having a TaggedUnique type to allow misalignment during storage that would provide conveniences for masking off or extracting the align-bits. I updated the stdlib so everyone but HashMap is now setting their dangling Unique/Shared pointers to , and deprecated . Shared and Unique now have constructors that will handle this for you (bonus: they're safe, unlike ). It would be backwards compatible to require alignment now, and abandon it later if it turns out to be more trouble than it's worth. However all current nightly users of Shared/Unique may miss this is a new requirement.
+1 to stabilizing can always be replaced with (plus maybe impls for or ), why shouldn’t it be removed entirely? all the potential uses of that I know of, all but one can/should use (which in turn uses internally). The remaining one is , it can not use in its current API either because ’s field is private, which prevents it from being matched in a pattern. So I have no desire to see the current stabilized. I’d like to see something else that would allow pattern matching, but I don’t know how to do that without also introducing unsoundness. (A public field could be set to zero.)
I'm actually most excited about myself. It's very useful for integer ID values, where a value of 0 is an invalid ID. Wrapping these types in would allow them to be wrapped in an at no extra cost in space. Using an is much more ergonomic than checking for everywhere (it's basically the same issue as nullable pointers).
I frequently use with integers as well; though what I really want is (since I am always doing this with indices, and is a perfectly good index). I tend to write some newtype to mask it for me.
Or -1, which is commonly used to indicate an invalid index. One way to do this with the current is to add 1 to whatever value you are storing (0 =None, 1 =Some(0), 2 =Some(1), etc).
Stabilizing probably involves stabilizing the trait and re-exporting them in . Is / the desired module name?
Zeroable shouldn't need to be stabilized, I don't think?
I think that stabilizing APIs that have bounds on a trait without stabilizing that trait should not become a habit. It’s been done a couple times, and is maybe acceptable when we have yet to figure out some details of the trait before stabilizing it, but I don’t think we should do it if the trait does not have a path to stabilization at all.
At some point, doesn't this turn into a discussion of what generalized properties should be encoded in the type system (with the extreme case being full-on refinement types)? I'm not trying to shut this discussion down, but in fact do the opposite - I think it'd be an interesting exercise to consider the total scope of properties of the form "this variable can only take values in this subset of its domain" that we might want to encode in the type system. We've already mentioned non-zero, non-max, and non-negative. What others would be reasonable/useful?
This is very out of scope for this issue, IMO.
I still want the "common" constructor of to be . It's safe, a noop and you're doing the check somewhere anyway (except for some unsafe APIs). We could really be using as the signature.
Yes. I’ve opened to do this. With that change, I’d like to propose FCP to stabilize . It’s been around for more than long enough, and I think we’ll have addressed all known concerns. I’m not proposing to stabilize (yet) because its value over seems uncertain. And not either because I think we should not stabilize an API that involves a trait bound without stabilizing that trait, and I feel is not polished enough (though I don’t have a concrete proposal for it, sorry).
A hack to get the equivalent of , , or on stable Rust is to abuse (in a properly encapsulated struct): (I’m not sure who invented/discovered it first.
I think it was emilio or mystor.
It was actually though he may be embarrassed to admit it. ;-)
I invented that technique independently too. However, in case of I fear that compiler could "optimize" the reference into NULL, since doesn't actually exist.
There is no fear to have, this can't happen.
Seems like I got confused .
That RFC would break too much code to justify implementing it in Rust 3.0.
Back on topic: I still want the "common" constructor of NonZero to be T -Option<NonZero<T. Something came up in this PR’s discussion. I renamed the existing constructors to and changed all usage with . It turns out that most uses, at least in the standard library, did not do a zero/null check themselves because the value is known to be non-zero / non-null, for example a pointer from . So if changed to the checked constructor they would use . It’s debatable which of an block or using is preferable. I think we should have both checked and unchecked constructors. I don’t mind much which one is "the default" (which one gets to be named ). Thoughts?
When creating newtypes with invariants I (almost?) always provide and . I see no reason why standard library should do it differently.
Yes, + is the precedent in the standard library too. Thought to be honest I care more about pushing this stuff to stabilization than about exact naming. I wouldn’t really mind + .
Then the type should reflect that (e.g. in allocators). is a bit unfortunate I suppose.
We could add a method for unsafe-but-not-FFI use cases like
and/or are a bit closer to what is.
Perhaps also add conversions between , , and ?
I'm proposing FCP for , though feel free to argue for stabilization of other pieces as well. fcp merge
While I’m happy to see progress happening, we should decide on first.
Any reason why there's no ? I think might be used in safe code too to guarantee that some number is not zero. That would mean is probably preferable.
ah, hadn't gotten there in my inbox triage yet. I'm basically with I think it's fine to have both variants, don't have a strong opinion on which should be the "default", except that it should match expected/existing usage. do you have thoughts?
Team member has proposed to merge this. The next step is review by the rest of the tagged teams: [ ] [ ] [x] [x] [ ] [ ] [ ] Concerns: resolved by Once these reviewers reach consensus, this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See for info about what commands tagged team members can give me.
concern new-unchecked Just to make sure we don't lose this... I'm not even sure if proposed stabilization covers this method, but I'm sort of assuming it does. This method has not landed yet and is proposed in . I feel that it's not ready yet because it was but all existing uses of now use , which to me seems like we're calling the "idiomatic constructor" and the rarely used constructor . I think we may want a better balance of concerns here, more conversions as mentioned above, or something before stabilizing such a method.
The status quo is that is unchecked (and unsafe) and is the only constructor. I think that adding checked constructors is uncontroversial. So options are: and and and They correspond respectively to the first commit of , the first two commits, and all three commits.
Given what I've currently seen (everything in libstd uses the "unchecked constructor") I'd avocate omitting a checked constructor from a first pass at stabilization.
Just to be clear, this is intended to mean "nothing currently in wants the checked constructor", rather than "nothing uses it because it doesn't yet exist"?
There’s some of both. Alright, I went through every call site changed in (which I initially made mechanically with ). Results below It’s not as clear-cut as suggests. First, most calls could be made unnecessary. Of the few remaining ones, most could be either unchecked or checked + unwrapping. I think we generally prefer safety by default (for example with checked slice indexing), resorting to unsafety when some piece of code turns out to be part of hot loops and the optimizer turns out to be unable to prove enough invariants to eliminate checks. But it’s not clear at all that this trade-off was made consciously in any case here, since the checked constructors did not exist before that PR. I counted 31 call sites outside of tests. 21 can be replaced with new APIs that encode non-zeroness in their signature, removing the need for checking or unsafely assuming: Adding conversions between , , , and possibly , with up to 6 new impls of the trait. This would replace 2 calls directly, and more when combined with following items. Various memory allocations APIs like return a pointer that is guaranteed to be non-null. They should encode this in their signature by returning e.g. instead of . Would replace 5 calls. also returns a that is guaranteed to be non-null. A new method could be , replacing 9 calls. 2 calls have a parameter of the form perhaps should return ? 2 calls convert their argument from to . More impls? uses . This could be replace by a new method that returns its field as such, not just as . One call (in ) does an explicit null check, and could match on the return value of a checked constructor instead. Three calls are in functions that are themselves unsafe, take a parameter, and document that the caller must not pass null pointers. Since unsafety is already involved, these probably should keep using the unchecked constructor. (If these APIs were not stable already, we should consider making them take or instead.) 6 calls use the unchecked constructor in an unsafe block, but could just as well use the checked one and then use .It’s a subjective call whether unsafety or unwrapping is preferable. and are constructors based on , whose return value is always = 1. One call has an argument of the form . Three calls do manual pointer tagging (starting from or ), so impls wouldn’t help there.
By the way, this shows that and are mostly interchangeable. According to the only difference is that has additional non-aliasing semantics that could potentially enable future optimizations. But such optimizations apparently don’t exist yet, so they’re effectively the same in today’s compilers. Is it really worth having two separate types? The name mostly only makes sense when opposed to . If the two types were to be merged into one, what should it be called?
I like your analysis very much! More conversion impls and some refactoring seem like way to go for me.
Hm with that information I'm not sure I understand the rationale for having a checked constructor. It seems like there's one btree location that wants a checked part (maybe) and others don't? Otherwise if we have to overhaul everything and add dozens of conversions, why don't we just stick with the status quote as an function? Are usage contexts for these types not already incredibly unsafe regardless?
The unsafe unchecked constructor is not going away. I’m proposing adding additional APIs to make unnecessary in most cases.
I've encountered many instances when I knew a value can't be zero and wanted to express it. is perfect fit for this because it also enables compiler optimization. It'd suck if all the code that want's to create would have to use - that is exactly what is not the design goal of Rust. For one example, look at recently merged PR. There is newtype and probably could be . (Well, according to PID 0 can be scheduler, but I don't know how useful is that in practice.) Why using there? Also (and ) accepts non-zero size (sadly, changing the API to accept would be breaking change.) I wonder how much hits would we get from running . I believe that is basically a newtype and it definitely should have safe constructor.
I’ve commits to to do some of this.
To clarify, does this mean that the only difference between and is that the latter cannot be null?
also has the correct Send/Sync impls and the correct variance via PhantomData.
Shared doesn't have Send/Sync impls
Oh, right
Looks like , just ownership of a for the purposes of the dropck rule.
The libs team talked about this issue a bit in our meeting today: We agreed with that proving checked default constructors, and unchecked variants, is the right way to go. In particular, it would be easy to think that was just another form of raw pointer, and that using it with null is perfectly fine. If you're doing so within already-unsafe blocks, you could get UB without ever realizing it. At the very least, the variants give you a heads up that there's a relevant contract.As to the / distinction: this seems to come down, to some degree, on what we're ultimately trying to achieve with these types. The original vision, as I understand it, was for these types to be aids in writing unsafe code correctly. The distinction signals intent, and at least aids with auto traits. On the other hand, we could instead see these types as essentially a way to get a stable type, in which case unifying them would be fine. Writing this up, it occurs to me that these two perspectives on the types are not mutually-exclusive: we could stabilize now and consider the others later. Once we reach consensus on this point, I think we're ready to go.
resolved new-unchecked The has been updated with and such conversions, and looks good to me.
As I believe I've stated above. I am happy with publically stabilizing Shared (what you call NonZeroPtr) and keeping Unique alive in the stdlib. It's nice-to-have and has no cost for us. I am massively apathetic about naming at this point. Shared could be called UnsafePtr or RawPtr or Ptr. I don't want NonZero in the name, though (if you want a Totally Honest name you need to call it NonZeroCovariantPtrThatMaybeOwns).
Would have the same ownership semantics as , or would it literally just be " except that it can't be zero"?
I am like 50% sure the ownership part is actually meaningless now. It only mattered for dropck when we did it, and I think the dropck aspect has been removed.
They still both contain whereas doesn’t. Does that not affect dropck, if contains a reference with a lifetime?
I'm saying the latest version of dropck doesn't contain the same magic that made this matter. Specifically PhantomData<Tturned off magic, and now it's just always off, with unsafe opt-in attributes. I'm verifying this now.
Shared appears to behave identically to now, meaning PhantomData<Tis no longer important for Shared. Its only uses are making something invariant and deriving Send/Sync, neither of which are used by Shared. The only question is if this will be true for all eternity. I think so, but I need to verify with and
I’m in favor of replacing both and with <s</s, and stabilizing that.
I'd use as the name, but agree with the rest.
Is this implicitly admitting that the vs. distinction was a mistake? (considering that we don't seem intent on preserving the distinction here)
(For what it’s worth, the distinction between and is already unrelated to that between and .)
(Yeah I know, collapsing down to a single type just brings it into even starker relief.)
The entire point of Shared and Unique is "wow everything about raw pointers suck for writing actual Rust code, let's redo them". There's reasons for every aspect of the raw pointer design, but the final result is unpleasant. vs is broadly useless in practice, but this is mostly a factor of their variance, which forces us to use and cast everywhere. In principle the variance they have is good, in that it's a safe default, but it's ultimately frustrating because of how variance works (invariance is irreversible). Supposedly having both is useful for FFI; I have no strong opinions on this. The fact that they're non-null is frustrating, as it makes us jump through hoops for optimizations, while making unsafe code less rustic. Them being nullable is ostensibly a safe default for their use in FFI. Swift notably made its unsafe pointers non-nullable, but it makes Optionals a lot more ergonomic too. The (now dead?) "owns a T" design was a bad default because it forced developers to know about some obscure thing and opt out of it or risk UB.
It might be interesting if we could guarantee the the memory layout of (or whatever it ends up being called) for FFI.
Correction: felix has produced an example where PhantomData implying ownership is live-and-well (which I've edited down for clarity). Produces: But if you toggle the commented out line in v3: This is a very interesting quote that I want to investigate, though:
I want to ask about the use of this in FFI function definitions. Say I have: It would be nice (for some form of nice which probably can't exist in FFI land...) if you could express this as: Instead. Is there a reason this isn't possible? Is this something that could be pursued or not?
I think this would be valid if we add to the type definitions… once that’s implemented: And I think we should.
Status update: this is currently waiting on tracking down the details relevant to the question he raised.
Forgive my ignorance, but is what allows of references to be optimised as nullable pointers? Would it be possible to do a similar thing for of floating point types, using the special case of ? I understand that technically isn't a kind of but it can represent the absence of a value.
Not by default, no. NaN is a totally valid floating point value. Null is not a valid value for a reference. You could have a that wraps around floats to mark them as "never NaN". I'm skeptical this will be very useful.
Please direct all future enum optimization requests to
fcp cancel Calling off FCP until has a chance to sort out details around .
proposal cancelled.
The concern has been resolved in So I’d like to propose now: Rename to and stabilize it. (Being in the module is enough to say that it’s a pointer. I’m not very attached to this specific name though.) Rename methods / to / (or whatever names are deemed appropriate), replace with in their signatures, and stabilize them. Replace with in the signatures of methods of the trait. Mark “permanently-unstable” by replacing remaining occurrences of with: (Maybe the string is only useful on the struct definition.) Ideally it would be made private to some crate instead, but it needs to be used in both liballoc and libstd. (Leave and unstable for now, and subject to future bikeshedding.)
Instead of , now that we have , would it be possible to make () the invalid value for pointers? It's anyway usually not possible to put anything meaningful or even allocate something there, and it would automatically allow optimisations for pointers without wrappers.
is documented as being represented as NULL: Changing that would like break code that uses FFI or/and . Similarly for and , and maybe also other smart pointers. Representing in the type system that a pointer is non-null is useful, regardless of memory layout.
implements this.
That would make undefined behavior, wouldn't it?
creating raw pointer with invalid value isn't UB. Did you mean something else?
They meant that cannot be used for the value in because is a totally legit Rust value.
Well, yes, that would be breaking change in exchange of allowing to become a valid value. Currently it's not, even though NULL is very popular and much more likely to occur as a real pointer through FFI, so each , etc. call currently needs to be guarded with because officially neither of these APIs accept yet don't reject it. Although I realise that such breaking change is probably impossible at this point and unlikely to be accepted, the FFI situation with NULL pointers is currently somewhat fragile and I'd love if it would be possible to accept them as any others in such APIs without guards.
I’m not sure if you already know that and are only using a writing shorthand, but is a valid value of today, and that won’t change. NULL is only forbidden for types that contain , or . And for / NULL not really a special case: callers of for example need to ensure that the pointer points to valid memory, not just that it is non-null.
This isn't about probabilities. "Likely" and "unlikely" do not matter, only "possible" and "impossible" do. Raw pointers represent C pointers and hence every value is possible. requires much more than non-NULL-ness. It requires the pointer to also be aligned and pointing to a valid allocation and whatever it points to must not be mutated for the duration of the lifetime. The last two points cannot be tested for during execution. That's why these functions are : They accept way fewer arguments than their type gives away.
Yes, thanks, I was using shorthand for reference; should've clarified that. The thing special about null is that zero-length slices quite commonly don't have such requirement in C libraries, and Rust doesn't read memory from zero-length slices either, but because of that requirement one needs to wrap each call into . That's the only thing that bothers me as it's easy to miss even with block, and it's not very clear why Rust itself can't enforce this by creating internally instead of having a mention in docs (that would have almost zero overhead while would make these functions somewhat easier to use).
Just wonder why is not as Rust's NPO guarantees that this is no-op.
It happens to compile to a no-op after optimizations for primitive integer and pointer/reference types, but it is implemented with an which is currently not allowed in . With Miri integration hopefully it can become a later.
Why it isn't implemented as ? That'd allow const evaluation even now.
Or just , as it's guaranteed to be no-op by language. Edit: Nevermind, for , I found that transmute requires miri integration to be const fn
The point is to conditionally return or
that’s an… interesting idea. But I just tried and hit . is a public trait that any crate can implement for its types, but that doesn’t change the memory layout of e.g. , so would be incorrect. In fact, the size of and might not be the same, and trying to does cause .
should be FWIW, but is checked too early for this, I guess.
Ah yeah that's the point, I think should be , and also auto-impl. As I understand, has same size as and is identical with , as is used by compiler to perform NPO(Please tell me if this is wrong). Then something like this can be possible. Does this code makes sense?
We should maybe abuse trait privacy (if we can, at all) to make it impossible to implement the trait outside of - we don't really support more types than primitives, in .
I was hoping to land and get / out of the way first, but my plan is to propose removing the trait and replace with 12 types like and , similar to atomic integer types. That way we avoid the questions of making the trait an auto trait or attempting to prevent more impls of it, since there is no trait.
Assuming you mean via a hidden private , then you don't even need to change to compiler.
Right, I meant "remove" as far as the public API is concerned. We can have a private generic type (with or without a trait bound) in the implementation, or whatever’s easier to maintain for the compiler.
Shared is now renamed NonNull and stable; Unique is a permanently-unstable internal implementation detail of std: This only leaves NonZero for this tracking issue, which is now mostly only useful for integers. I just published which propose adding 12 concrete types like , deprecating NonZero, and later making it private. That last step would (finally!) close this tracking issue.
Also some NonNull follow up:
Implementation PR, ready to merge: Add new types in and Deprecate After whatever time is appropriate for the deprecation period of unstable features, we can land to make private and leave just enough in it to support its public wrappers.
Hm, this probably way too late, but are we sure that the name should be ? It seems to me that overemphasizes, well, non-nullness of this type, while in fact the real trick is, in my understanding, covariant . At least, some folks on Reddit emphasize optimizations over variance: :) Would just a be a better name? EDIT: nvm, see that this already was discussed in another issue:
The enum optimization is my motivation for pushing this feature to stabilization, FWIW. I think you could already get covariance before by using (or wrapping it in some other type outside of std). This aspect of is just library code, there is no compiler magic. Also it hasn’t happened to me to actively change some code to make it covariant. (Though maybe the stuff I used was already covariant and I just didn’t realize that was important?)
Tracking issue for the new types:

Discussion:
/// building abstractions like `Rc<T>` or `Arc<T>`, which internally /// use raw pointers to manage the memory that they own. #[unstable(feature = "shared", reason = "needs an RFC to flesh out design", <del> issue = "0")] </del> <ins> issue = "27730")] </ins> pub struct Shared<T: ?Sized> { pointer: NonZero<*const T>, // NOTE: this marker has no consequences for variance, but is necessary

/// `Shared` pointers are not `Send` because the data they reference may be aliased. // NB: This impl is unnecessary, but should provide better error messages. <del> #[unstable(feature = "shared", issue = "0")] </del> <ins> #[unstable(feature = "shared", issue = "27730")] </ins> impl<T: ?Sized> !Send for Shared<T> { } /// `Shared` pointers are not `Sync` because the data they reference may be aliased. // NB: This impl is unnecessary, but should provide better error messages. <del> #[unstable(feature = "shared", issue = "0")] </del> <ins> #[unstable(feature = "shared", issue = "27730")] </ins> impl<T: ?Sized> !Sync for Shared<T> { } <del> #[unstable(feature = "shared", issue = "0")] </del> <ins> #[unstable(feature = "shared", issue = "27730")] </ins> impl<T: ?Sized> Shared<T> { /// Creates a new `Shared`. pub unsafe fn new(ptr: *mut T) -> Self {

} } <del> #[unstable(feature = "shared", issue = "0")] </del> <ins> #[unstable(feature = "shared", issue = "27730")] </ins> impl<T: ?Sized> Clone for Shared<T> { fn clone(&self) -> Self { *self } } <del> #[unstable(feature = "shared", issue = "0")] </del> <ins> #[unstable(feature = "shared", issue = "27730")] </ins> impl<T: ?Sized> Copy for Shared<T> { } #[cfg(not(stage0))] // remove cfg after new snapshot <del> #[unstable(feature = "shared", issue = "0")] </del> <ins> #[unstable(feature = "shared", issue = "27730")] </ins> impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsize<U> { } <del> #[unstable(feature = "shared", issue = "0")] </del> <ins> #[unstable(feature = "shared", issue = "27730")] </ins> impl<T: ?Sized> Deref for Shared<T> { type Target = *mut T;

} } <del> #[unstable(feature = "shared", issue = "0")] </del> <ins> #[unstable(feature = "shared", issue = "27730")] </ins> impl<T> fmt::Pointer for Shared<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Pointer::fmt(&*self.pointer, f)