Skip to content
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

Mark enums with non-zero discriminant as non-zero #37224

Merged
merged 1 commit into from
Oct 19, 2016

Conversation

petrochenkov
Copy link
Contributor

Copy link
Member

@eddyb eddyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM although I believe it could be simpler.

@@ -769,6 +770,7 @@ pub enum Layout {
CEnum {
discr: Integer,
signed: bool,
non_zero: bool,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You already have the range (see rustc_trans::adt for a way to determine if a value is in the range), why would this additional field be needed?

Copy link
Contributor Author

@petrochenkov petrochenkov Oct 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enum E {
    A = -1,
    B = 1,
}

0 is in the range, but the enum is still non-zero.
(Also, non_zero: bool fits into previous padding so it doesn't increase the size of Layout)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's annoying. What I expect to eventually have would use 2 there, that's why I don't like non_zero: it's a special-case that makes sense mostly on pointers.
If you want to discuss the full niche optimization, I'd be down for it (IRC?).
If you don't want to change this implementation I'll r+ and take out this later (and/or switch to multi-ranges - LLVM actually supports them for !range).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't plan to implement the full optimization so far.

CEnum { discr: value, .. } => {
return success(RawNullablePointer {
nndiscr: discr as u64,
value: Int(value)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make this match produce the Primitive type and do the return after the match?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

@@ -15,6 +15,8 @@
#![feature(test)]
#![feature(libc)]

#![cfg_attr(stage0, feature(question_mark))]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few people hit this, I guess it got removed by accident. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that #37177 already contains this (and is in the queue)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#37202 contains it too :D
The sooner it lands the better.

@eddyb
Copy link
Member

eddyb commented Oct 16, 2016

@bors r+

@bors
Copy link
Contributor

bors commented Oct 16, 2016

📌 Commit 49e6b46 has been approved by eddyb

@bluss bluss added the relnotes Marks issues that should be documented in the release notes of the next release. label Oct 17, 2016
eddyb added a commit to eddyb/rust that referenced this pull request Oct 19, 2016
Mark enums with non-zero discriminant as non-zero

cc rust-lang/rfcs#1230
r? @eddyb
eddyb added a commit to eddyb/rust that referenced this pull request Oct 19, 2016
Mark enums with non-zero discriminant as non-zero

cc rust-lang/rfcs#1230
r? @eddyb
bors added a commit that referenced this pull request Oct 19, 2016
@bors bors merged commit 49e6b46 into rust-lang:master Oct 19, 2016
@Manishearth
Copy link
Member

Btw, this caused some rather tricky issues in Servo (rust-lang/rust-bindgen#225).

IMO when changing reprs for things which may come from FFI (e.g. an enum) we should be more careful and have a cycle of warnings or a compiler note or something. Not sure how it would be implemented. (I agree that it's non ideal for C++ to abuse enums as bitflags but apparently it's a common pattern)

The only reason we could figure this out was because I knew how Rust's encoded enum debuginfo works, and I also knew that this PR had happened -- which is a rather high bar for being able to debug things like this. It's otherwise quite an opaque and nonsensical bug that feels like a compiler bug (in this case, setting foo = Some(thing) made it stay None)

cc @eddyb @nikomatsakis

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Nov 8, 2016

Hmm. @Manishearth I've not read this PR, but I assume that the enums in question were not marked as #[repr(C)] or any such thing?

(In which case, was the "safe for C" lint not firing, or was it disabled?)

@Manishearth
Copy link
Member

They were marked as repr(u8) which IIRC is equivalent?

@eddyb
Copy link
Member

eddyb commented Nov 8, 2016

That's just setting the size of the enum, it's still UB to have a value other than the assigned ones.
EDIT: Not saying #[repr(C)] doesn't also have that UB property still, neither escape it.
EDIT2: Looks like gross misuse, nothing to see here.

@petrochenkov petrochenkov deleted the nz branch March 16, 2017 19:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants