Skip to content

fix is_non_exhaustive confusion between structs and enums #53721

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

Merged
merged 2 commits into from
Sep 6, 2018

Conversation

arielb1
Copy link
Contributor

@arielb1 arielb1 commented Aug 26, 2018

Structs and enums can both be non-exhaustive, with a very different
meaning. This PR splits is_non_exhaustive to 2 separate functions - 1
for structs, and another for enums, and fixes the places that got the
usage confused.

Fixes #53549.

r? @eddyb

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 26, 2018
@arielb1 arielb1 force-pushed the exhaustively-unpun branch from c16028f to 37b9455 Compare August 26, 2018 14:02
@rust-highfive

This comment has been minimized.

Structs and enums can both be non-exhaustive, with a very different
meaning. This PR splits `is_non_exhaustive` to 2 separate functions - 1
for structs, and another for enums, and fixes the places that got the
usage confused.

Fixes rust-lang#53549.
@@ -1981,10 +1981,30 @@ impl<'a, 'gcx, 'tcx> AdtDef {
}

#[inline]
pub fn is_non_exhaustive(&self) -> bool {
fn is_non_exhaustive(&self) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would rename this to has_nonexhaustive_flag and add a comment about how the meaning of this flag depends a lot on the kind of the ADT. Personally, I find this setup pretty unfortunate: I think we should be "desugaring" the flag so that it appears on the variant for structs and on the adt only for enums (as I described here). But I guess we can separate that out as a distinct sort of refactoring.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure, that looks like something that should be done when we implement per-variant exhaustive.

self.flags.intersects(AdtFlags::IS_NON_EXHAUSTIVE)
}

#[inline]
pub fn is_enum_non_exhaustive(&self) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should call this method:

can_extend_variant_list

and add a suitable comment explaining how it is derived from a #[non_exhaustive] that appears on the enum (but not a variant).

}

#[inline]
pub fn is_univariant_non_exhaustive(&self) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should call this method:

can_extend_field_list

and -- really -- I think it should be on the variant. But if we want to keep it here, perhaps a name like can_extend_univariant_field_list (again with a comment linking to how it maps to Rust source).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nikomatsakis

Normally you are suppose to call is_variant_non_exhaustive, which takes both the AdtDef and the VariantDef.

This is just s a shortcut method because someone removed the old .struct_variant() method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Wait it just got renamed to non_enum_variant. I'll just handle that.

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 like to use the name nonexhaustive here, because that's how the feature is called.

@nikomatsakis nikomatsakis self-assigned this Aug 30, 2018
This completely splits the IS_NON_EXHAUSTIVE flag. No functional
changes intended.
@arielb1
Copy link
Contributor Author

arielb1 commented Sep 1, 2018

pushed..

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Collaborator

bors commented Sep 5, 2018

📌 Commit ae2ad30 has been approved by nikomatsakis

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 5, 2018
@bors
Copy link
Collaborator

bors commented Sep 6, 2018

⌛ Testing commit ae2ad30 with merge 20ca025...

bors added a commit that referenced this pull request Sep 6, 2018
fix `is_non_exhaustive` confusion between structs and enums

Structs and enums can both be non-exhaustive, with a very different
meaning. This PR splits `is_non_exhaustive` to 2 separate functions - 1
for structs, and another for enums, and fixes the places that got the
usage confused.

Fixes #53549.

r? @eddyb
@bors
Copy link
Collaborator

bors commented Sep 6, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: nikomatsakis
Pushing 20ca025 to master...

@bors bors merged commit ae2ad30 into rust-lang:master Sep 6, 2018
@nnethercote
Copy link
Contributor

This hurt compile times by up to 3%, mostly for shorter-running benchmarks:
https://perf.rust-lang.org/compare.html?start=27e5457f3fa6c6e322e05352f0109f2cd511396c&end=20ca02569ae3e1dc29962e92739fbab632abf241&stat=instructions:u

@arielb1: any thoughts?

@arielb1
Copy link
Contributor Author

arielb1 commented Sep 22, 2018

Some bug? This commit should not change performance.

@arielb1
Copy link
Contributor Author

arielb1 commented Sep 22, 2018

Looks like alloc_adt_def is taking much more time for some reason - at least on my callgrind. This at least makes sense.

@arielb1
Copy link
Contributor Author

arielb1 commented Sep 22, 2018

Ah decoding of item attrs is duplicated between a struct and its constructor:
https://github.com/rust-lang/rust/blob/master/src/librustc_metadata/decoder.rs#L925-L930

The code I have written uses the constructor's attrs in VariantDef::new, and the ADT's attrs in AdtDef::new, which causes the double decoding.

arielb1 added a commit to arielb1/rust that referenced this pull request Sep 22, 2018
During metadata loading, the AdtDefs for every ADT in the universe need
to be loaded (for example, for coherence of builtin traits). For that,
the attributes of the AdtDef need to be loaded too.

The attributes of a struct are duplicated between 2 def ids - the
constructor def-id, and the "type" def id. Loading attributes for both
def-ids, which was done in rust-lang#53721, slowed the compilation of small
crates by 2-3%. This PR makes sure we only load the attributes for the
"type" def-id, avoiding the slowdown.
bors added a commit that referenced this pull request Sep 23, 2018
avoid loading constructor attributes in AdtDef decoding

During metadata loading, the AdtDefs for every ADT in the universe need
to be loaded (for example, for coherence of builtin traits). For that,
the attributes of the AdtDef need to be loaded too.

The attributes of a struct are duplicated between 2 def ids - the
constructor def-id, and the "type" def id. Loading attributes for both
def-ids, which was done in #53721, slowed the compilation of small
crates by 2-3%. This PR makes sure we only load the attributes for the
"type" def-id, avoiding the slowdown.

r? @eddyb & cc @nnethercote
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[nightly regression] E0639 + adding #[non_exhaustive] to io::ErrorKind is a breaking change
6 participants