-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Tracking issue for RFC 1892, "Deprecate uninitialized in favor of a new MaybeUninit type" #53491
Comments
cc @RalfJung |
I can help implement the RFC. |
Awesome, I can help reviewing :) |
I'd like some clarification on this part of the RFC:
Should only |
AFAIK we only do the really harmful code generation for So I'd do it for |
We could start off by making this: rust/src/librustc_codegen_llvm/intrinsic.rs Lines 184 to 198 in 8928de7
check whether rust/src/librustc_codegen_llvm/mir/operand.rs Lines 400 to 403 in 8928de7
Once you've seen the trap (i.e. rust/src/librustc_codegen_llvm/mir/block.rs Lines 445 to 447 in 8928de7
To actually panic, you'd need something like this: rust/src/librustc_codegen_llvm/mir/block.rs Lines 360 to 407 in 8928de7
(you can ignore the EvalErrorKind::BoundsCheck arm)
|
@eddyb Thanks for the pointers. I'm now fixing (several) deprecation warnings and I feel (very) tempted to just run |
That would exactly miss the point, yeah.^^ At least for now, I would like to consider It also says that for I'm afraid all these uses of |
This gives me an idea... perhaps we should lint (group: "correctness") for this sort of code? cc @oli-obk |
We should only ship Nightly with those warnings once the recommended replacement is available at least on Stable. See similar discussion at #52994 (comment) |
You've participated in discussion about this before, but I'll post here to circulate more widely: this is already something we have many existing use-cases for in Fuchsia, and we have a trait for this (
Yeah, this is an aspect in which |
Those discussions were about ways of allowing safe The consensus also was that it would be unsound for any approach discussed to allow reading padding bytes, which are a form of uninitialized memory, in safe Rust. That is if you put initialized memory in, you can't get uninitialized memory out. IIRC, nobody there suggested or discussed any approach in which you could put uninitialized memory in and get initialized memory out, so I don't follow what those discussions have to do with this one. To me they are completely orthogonal. |
To drive the point home a bit more, LLVM defines uninitialized data as Poison, which is distinct from "some arbitrary but valid bit pattern." Branching based on a Poison value or using it to compute an address which is then dereferenced is UB. So, unfortunately, "types where all bit patterns are okay" are still not safe to construct because using them without separately initializing them will be UB. |
Right, sorry, I should have clarified what I meant. I was trying to say that "types where all bit patterns are okay" is already something that we're interested in defining for other reasons. Like @RalfJung said above,
|
Thank god there are people who can read, because apparently I can't... |
Right, so what I meant to say is: We definitely have types where all initialized bit patterns are okay -- all the What is an open question is under which circumstances which of these types are allowed to be uninitialized, i.e., poison. My own preferred answer is "never".
Reading padding bytes as |
The discussion in a nutshell was about providing a trait, It was proposed that it should be I have no idea what any of this has to do with The only thing I can imagine is that we could add a blanket impl: |
@gnzlbg back then you were talking about |
I discussed this proposal with @nikomatsakis at RustConf, and he encouraged me to go forward with an RFC. I was going to do it in a few weeks, but if there's interest, I can try getting one done this weekend. Would that be useful for this discussion? |
@joshlf which proposal are you talking about? |
A |
@joshlf I think such a pair of traits would more build on top of this discussion than be part of it. AFAIK we have two open questions in terms of validity:
|
@SimonSapin see the unstable |
@RalfJung maybe |
@Stargateur Absolutely, this is definitely not going to be stabilized with its current name. It is hopefully not going to get stabilized ever if #49147 happens Soon (TM). |
@RalfJung Ugh, that's my fault, I was blocking the PR without a great reason: #61749 (comment) |
This comment has been minimized.
This comment has been minimized.
Mystery solved: the uses of the repeat expression in libcore actually were for types that are copy. And the reason it doesn't work in liballoc is that |
@RalfJung Maybe open a PR removing uses of the macro where it's completely unnecessary? |
Regarding
|
Similar to what @danielhenrymantilla wrote about |
@RalfJung I have a question about this: fn foo<T>() -> T {
let newt = unsafe { MaybeUninit::<T>::zeroed().assume_init() };
newt
} For example, we call |
@Pzixel code can only cause UB when it runs. So, The property of being valid for all possible ways to call is called "soundness", also see the reference. The general contract in Rust is that the safe API surface of a library must be sound. This so that users of a library do not have to worry about UB. The entire safety story of Rust rests on libraries with sound APIs. |
@RalfJung thanks. So if I get you correctly this function is unsound (and thus, invalid), but if we mark it as |
@Pzixel if you mark it unsafe, soundness is just not a concept that even applies any more. "Is this sound" only makes sense as a question for safe code. Yes, you should mark the function |
Yes, of course, I understand that. I only wanted to conclude that partial functuon must be marked as |
Since the discussion on this tracking issue is so long now, can we break it out into a few other tracking issues for each feature of
|
Seems reasonable. There also is #63291. |
Closing this in favor of a meta-issue which tracks |
@RalfJung one more question please
Is it okay to not mark function as
|
@Pzixel I don't think there is community consensus on this matter. I personally would not accept such code if I had to review it -- safety should IMO be meaningful even inside a library implementation. I think it makes unsafe modules easier to write if you consistently follow this discipline. But "soundness" as a concept is defined in terms of clients using the public API of your type, so for soundness, the safety of private functions does not matter. |
NEW TRACKING ISSUE = #63566
This is a tracking issue for the RFC "Deprecate
uninitialized
in favor of a newMaybeUninit
type" (rust-lang/rfcs#1892).Steps:
Unresolved questions:
Should we have a safe setter that returns an&mut T
?Should we renameMaybeUninit
? (RenameMaybeUninit
toMaybeUninitialized
#56138)Should we renameinto_inner
? Should it be more liketake
instead and take&mut self
?ShouldMaybeUninit<T>
beCopy
forT: Copy
?get_ref
andget_mut
(but not reading from the returned references) before data got initialized? (AKA: "Are references to uninitialized data insta-UB, or only UB when being read from?") Should we rename it similar tointo_inner
?Can we make(done)into_inner
(or whatever it ends up being called) panic whenT
is uninhabited, likemem::uninitialized
does currently?Seems like we want to not deprecatemem::zeroed
. We should however remember to also update its documentation together withMaybeUninit
, make sure people are aware that this is insta-UB if all-0-bits does not satisfy the type's validity invariant.The text was updated successfully, but these errors were encountered: