Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upUninhabited types are ZSTs despite partial initialization being allowed in safe code. #49298
Comments
eddyb
added
A-codegen
I-nominated
T-compiler
labels
Mar 23, 2018
This comment has been minimized.
This comment has been minimized.
|
Seems I-unsound. enum Void {}
fn main() {
let mut x: (Void, [u8; 20]);
x.1 = [0x12; 20];
} |
eddyb
added
the
I-unsound 💥
label
Mar 23, 2018
This comment has been minimized.
This comment has been minimized.
|
Also, this regression was introduced in Rust 1.24.0 from what I see, this correctly works in 1.23.0. |
cuviper
added
the
C-bug
label
Mar 24, 2018
This comment has been minimized.
This comment has been minimized.
|
To pile on the scary labels, that also makes this a regression from stable to stable! |
scottmcm
added
the
regression-from-stable-to-stable
label
Mar 25, 2018
This comment has been minimized.
This comment has been minimized.
|
#48493 looks like an instance of this - cc @alexcrichton |
This comment has been minimized.
This comment has been minimized.
|
@eddyb |
This comment has been minimized.
This comment has been minimized.
|
@rkruppe is there a separate bug for that? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
There's potentially an even more problematic implication here: initializing an uninhabited (because of its fields) variant and panicking while doing so could also result in writing over data following the whole let x: Option<(String, !)>;
let y = vec!["foo".to_string()];
x = Some((String::new("bar"), panic!("{:?}", y)));This might be hard to demonstrate today, because of some extra temporaries, but optimizations would likely prefer to write to |
This comment has been minimized.
This comment has been minimized.
|
We discussed in the meeting. It seems like the rules want to be:
This ensures there is space for non-ZST data... we need to do this if we want to be able to optimize temporaries away pre-monomorphization. |
This comment has been minimized.
This comment has been minimized.
Specifically, the data inside the variant (not including any tag or anything else enum-specific). |
nikomatsakis
added
P-medium
and removed
I-nominated
labels
Apr 26, 2018
eddyb
self-assigned this
Apr 26, 2018
This was referenced Apr 26, 2018
eddyb
referenced this issue
May 10, 2018
Merged
rustc: leave space for fields of uninhabited types to allow partial initialization. #50622
bors
added a commit
that referenced
this issue
May 13, 2018
bors
closed this
in
#50622
May 13, 2018
rkruppe
referenced this issue
Jun 27, 2018
Closed
Remove use of uninitialized() in Weak::new() #51851
SimonSapin
referenced this issue
Jun 27, 2018
Closed
Weak::new() segfaults on uninhabited types #48493
scottmcm
referenced this issue
Jul 9, 2018
Open
Tracking issue for promoting `!` to a type (RFC 1216) #35121
RalfJung
referenced this issue
Nov 10, 2018
Merged
Forward the ABI of the non-zero sized fields of an union if they have the same ABI #55834
rkruppe
referenced this issue
Feb 11, 2019
Open
Consider aggregate types containing unconstructable types to also be unconstructable #58374
This comment has been minimized.
This comment has been minimized.
|
Shall there be some Related idea: |
This comment has been minimized.
This comment has been minimized.
|
@vi Note that, IIRC, Note that #49298 (comment) is more general than partial initialization, and it concerns writes to return destination, followed by a panic later, in the context of wanting to optimize away copies. |
This comment has been minimized.
This comment has been minimized.
|
This comment has been minimized.
This comment has been minimized.
|
Ah, right, I was thinking of a subtler distinction, nevermind. |
eddyb commentedMar 23, 2018
•
edited
When we optimized product types with uninhabited fields to be ZST, partial initialization was overlooked, i.e. writes to the inhabited sibling fields are allowed despite missing in the layout.
Thankfully, it's impossible to read or borrow such fields, because the whole value must be initialized (although this may be relaxed in the future). However , the initialized fields are still dropped.
One way we could work around this is track uninhabitedness but only take advantage of it in enums.
(
I am not aware of a solution that works withvariant types, which I think we should keep in mind.)EDIT: we can disallow creating the
enumfrom an incomplete variant. This is also required by niche optimizations because the niche slot being uninitialized would result in UB.EDIT2: incomplete variants might be possible today already (#49298 (comment)).
As an example, in debug mode, this snippet prints
0, becausex.1andyoverlap:cc @nikomatsakis @nagisa