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

Tracking issue for RFC 2008: Future-proofing enums/structs with #[non_exhaustive] attribute #44109

Closed
5 of 7 tasks
scottmcm opened this issue Aug 26, 2017 · 139 comments · Fixed by #64639
Closed
5 of 7 tasks
Labels
B-RFC-implemented B-unstable C-tracking-issue disposition-merge E-mentor F-non_exhaustive finished-final-comment-period T-lang

Comments

@scottmcm
Copy link
Member

scottmcm commented Aug 26, 2017

This is a tracking issue for the RFC "Future-proofing enums/structs with #[non_exhaustive] attribute" (rust-lang/rfcs#2008).

Steps:

Issues to be resolved prior to stabilization

@Mark-Simulacrum Mark-Simulacrum added B-RFC-approved T-lang C-tracking-issue labels Aug 26, 2017
@eddyb
Copy link
Member

eddyb commented Aug 26, 2017

I'd cc @rust-lang/compiler instead.

@tinaun
Copy link
Contributor

tinaun commented Aug 27, 2017

im working on a pr for this. how should tests be structured?

@tinaun
Copy link
Contributor

tinaun commented Aug 27, 2017

also: should there be a lint for #[non_exhaustive] on non public items, since it doesn't really do anything crate-locally?

@clarfonthey
Copy link
Contributor

clarfonthey commented Aug 27, 2017

@tinaun shouldn't they all go under the useless_attribute lint? That includes both on non-pub items and structs with private fields.

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Aug 28, 2017

@tinaun I would expect tests for this to be scattered about in the run-pass and compile-fail and ui directories:

  • run-pass would be used to test things that should compile
  • ui is usually used to test for things that don't compile (compile-fail can also be used, but I prefer ui personally)
    • if you want to test that a lint is issued, you can use #[deny] to convert the warning into an error

Just to keep things organized, I would make a subdirectory like src/test/run-pass/nonexhaustive-rfc2008 (and same for ui) to contain the tests.

So I would imagine using ui tests to check for:

  • Errors when exhaustively matching (without _) something from another crate that is tagged #[nonexhaustive]

The run-pass might be used to test that an exhaustive match within the same crate compiles just fine.

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Sep 15, 2017

@tinaun any progress? need any tips?

@tinaun
Copy link
Contributor

tinaun commented Sep 15, 2017

I'm currently away for the weekend but I would love to have some help with understanding the implementation of privacy in the complier. sorry for forgetting about this!

@petrochenkov
Copy link
Contributor

petrochenkov commented Sep 16, 2017

So, this feature shouldn't require too many changes to implement.

  • First, we need to require .. in patterns, this needs to be done in fn check_struct_pat_fields in librustc_typeck/check/_match.rs
  • Then we need to prohibit any struct expressions (with .. or not, doesn't matter), this needs to be done in fn check_expr_struct in librustc_typeck/check/mod.rs
  • After that we need to tweak visibilities for struct constructors. This currently requires changes to three places - 1) fn build_reduced_graph_for_item/ItemKind::Struct + fn build_reduced_graph_for_variant in librustc_resolve 2) fn encode_struct_ctor and fn encode_enum_variant_info in librustc_metadata and 3) fn def_id_visibility in librustc_privacy.
    I all cases visibility of a struct/variant with non_exhaustive attribute should be lowered to pub(crate) if it was pub.
    EDIT: Separating visibilities for enum variants and their constructors may potentially require some larger infrastructural changes because they share DefId currently, so non_exhaustive on tuple/unit variants can be omitted from initial implementation.
  • Test everything! In this case it's probably better to write failing tests before doing anything else and then make them pass gradually.
  • EDIT: I completely forgot about non_exhaustive on enums and match exhaustiveness checks.

@nikomatsakis nikomatsakis added E-mentor WG-compiler-middle T-compiler labels Sep 21, 2017
@nikomatsakis
Copy link
Contributor

nikomatsakis commented Sep 25, 2017

@tinaun just checking in -- did those instructions help? Still got questions? =)

UPDATE: @tinaun responded on Gitter.

@davidtwco
Copy link
Member

davidtwco commented Oct 13, 2017

Hoping to take a stab at this after speaking with @nikomatsakis in Gitter. @tinaun are you still working on this?

Update: @tinaun replied on Gitter.

@davidtwco
Copy link
Member

davidtwco commented Oct 15, 2017

@nikomatsakis @eddyb @arielb1 @pnkfelix (I'm not sure who I should be pinging about this, apologies)

So far I've implemented most of the mentoring instructions but there are a few things I've run into issues with.

In this section where I require .. (as per the first mentoring instruction) - this seems to work, except that it doesn't take into account whether the struct/enum is within the crate (and therefore should be able to match without a wildcard) - this causes issues with the run-pass/rfc-2008-non-exhaustive/struct_within_crate.rs test (and the similar enum test). I'm not sure what I should be checking to do that.

I've also not made changes to the visibilities in encode_enum_variant_info and build_reduced_graph_for_variant as when I did so, I found that I was no longer able to access the variants of a enum in order to match them from outside of a crate - similarly to the previous question, I wasn't sure how to have the change apply only outside of a crate.

I hope this is on the right track and I'd appreciate any feedback.

@arielb1
Copy link
Contributor

arielb1 commented Oct 16, 2017

@davidtwco

To check whether an ADT is within the same crate as the crate you are type-checking, find the def-id of the ADT and check whether it's local - e.g. if you have an adt: &AdtDef, you can check adt.did.is_local().

@arielb1
Copy link
Contributor

arielb1 commented Oct 16, 2017

For the visibility, you can ask @petrochenkov but I think you want to set the visibility to pub(crate) aka ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))

@arielb1
Copy link
Contributor

arielb1 commented Oct 16, 2017

If you can find me, feel free to ping me on IRC.

@davidtwco
Copy link
Member

davidtwco commented Oct 16, 2017

Thanks, that's super helpful.

With regards to the visibility, that's what I was setting the visibility to, but I'll take another stab at it and see what I can come up with.

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Oct 16, 2017

@davidtwco glad to see that @arielb1 got you unblocked! Looking forward to seeing the PR. =) Let us know if you hit any other problems (are here or on gitter)

@davidtwco
Copy link
Member

davidtwco commented Oct 17, 2017

@nikomatsakis @arielb1

Apologies for how long this is taking and for a further query.

Since my previous comment here I think I've got it working with structs and after speaking with @nikomatsakis in Gitter earlier today, I've added a bunch more tests for cases that I hadn't considered. There are only five tests that still don't pass:

The first of which is related to instantiating a tuple struct, I think I've went wrong with the visibility somewhere for this so I'm going to look into that. The second of which is similar but for instantiating a unit struct.

The rest of which are all related to a lack of errors for things that should fail on enums with the attribute. @nikomatsakis mentioned that there are two cases with enums, handling new variants and new fields to existing variants - I do believe that the new fields case is handled by the existing structs code but I'm not 100% sure. However, I don't think the new variants case is handled. The function mentioned in the first bullet point of the mentoring instructions doesn't seem to apply for this case and I've not been able to figure out where the equivalent is. As the edited mentoring instructions now mention, there aren't any instructions for handling enums so I've been struggling to pinpoint where I need to make changes. I'd appreciate some pointers as to where I should be working for that.

All the help so far as been fantastic so I appreciate that.

davidtwco added a commit to davidtwco/rust that referenced this issue Oct 6, 2019
This commit stabilizes RFC 2008 (rust-lang#44109) by removing the feature gate.

Signed-off-by: David Wood <david@davidtw.co>
@jonas-schievink jonas-schievink added F-non_exhaustive B-RFC-implemented B-unstable and removed B-RFC-approved labels Oct 6, 2019
@nikomatsakis
Copy link
Contributor

nikomatsakis commented Oct 9, 2019

@yodaldevoid I think the recording (and minutes) are available here

davidtwco added a commit to davidtwco/rust that referenced this issue Oct 14, 2019
This commit stabilizes RFC 2008 (rust-lang#44109) by removing the feature gate.

Signed-off-by: David Wood <david@davidtw.co>
@Kixunil

This comment has been minimized.

@Nemo157
Copy link
Member

Nemo157 commented Oct 17, 2019

@Kixunil that is how the feature works already.

@Kixunil
Copy link
Contributor

Kixunil commented Oct 17, 2019

@Nemo157 ah I missed that, awesome! Thank you!

davidtwco added a commit to davidtwco/rust that referenced this issue Oct 25, 2019
This commit stabilizes RFC 2008 (rust-lang#44109) by removing the feature gate.

Signed-off-by: David Wood <david@davidtw.co>
@bors bors closed this as completed in 959b6e3 Oct 25, 2019
est31 added a commit to est31/rcgen that referenced this issue Dec 19, 2019
This attribute replaces the _hidden field of the
struct, serving the same purpose.

For enums, we don't use the non_exhaustive feature
yet as we'd like to have exhaustivness checks
at least for our internal code.
For more, see this comment by @dtolnay [1]

It stabilized in Rust 1.40.0 which got released today.
The MSRV policy of this crate is to follow whatever
the currently latest released Rust version is.

[1]: rust-lang/rust#44109 (comment)
wip-sync pushed a commit to NetBSD/pkgsrc-wip that referenced this issue Feb 20, 2020
They've done a lot of cleaning up upstream and are no longer pulling in
stuff via commit hashes so we can remove all the _REV, DISTFILES, SITES
and post-extract stuff for librespot, tremor, etc.

- Back to having an odd SITES work-around for a CARGO_CRATE_DEPENDS:
  wasi-0.9.0 due to the version name.
- Need [Rust 1.40][1] for this owing to [whoami-0.7.0][2] and use of
  `#[non_exhaustive]` per [this issue][3]
- Back to having a patch for nix [per this commit][4] just
  because of the version being used (this is ultimately fixed upstream)
- Most other patches can be (and have been) removed though

[1]: https://github.com/rust-lang/rust/blob/master/RELEASES.md#version-1400-2019-12-19
[2]: https://github.com/libcala/whoami/blob/03b0b552f3732d1738b353415ef7dd7bb5555393/changelog.md#070---2019-12-21
[3]: rust-lang/rust#44109
[4]: https://wip.pkgsrc.org/cgi-bin/gitweb.cgi?p=pkgsrc-wip.git;a=commit;h=0a23b3b322a6313f27284baa499924921beeca73
@Dujunayan

This comment has been minimized.

@Dujunayan

This comment has been minimized.

@eddyb

This comment has been minimized.

@Dujunayan

This comment has been minimized.

@tesuji

This comment has been minimized.

@Centril
Copy link
Contributor

Centril commented Mar 30, 2020

This is not the place to discuss this. Please file a new issue for any problems you might have.

@rust-lang rust-lang locked as resolved and limited conversation to collaborators Mar 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
B-RFC-implemented B-unstable C-tracking-issue disposition-merge E-mentor F-non_exhaustive finished-final-comment-period T-lang
Projects
None yet
Development

Successfully merging a pull request may close this issue.