#[non_exhaustive
gender is a ‘#[non_exhaustive] enum’
gender is not a binary

gender is: a boolean, 0, 1, 2, "none", "limited", "full", "line-tables-only", or "line-directives-only"
June 16, 2026 at 3:53 PM
🦀 Avoiding Breaking Changes with Rust’s `non_exhaustive` attribute

> The non_exhaustive attribute indicates that a type or variant may have more fields or variants added in the future.

blog.implrust.com/posts/2025/0...

#rustlang
September 7, 2025 at 4:26 PM
I mean, they do use enums for oneof messages, so you do it the same way: `#[non_exhaustive]` and a catch-all _Unrecognized variant
August 28, 2026 at 12:44 AM
🦀#[non_exhaustive] attribute

- If you mark your enum with non_exhaustive attribute, it enforces users to always use wildcards in match statements

- You can add more variants to your library without breaking users' code; no major version bump required
September 5, 2025 at 4:09 PM
This is what `#[non_exhaustive]` and enum composition is for, though. Please never use strings as enum values in Rust if you can absolutely help it.
March 15, 2025 at 9:31 PM
🔒 #Rustlang Tip: Use the #[non_exhaustive] attribute for future-proofing your enums and structs.

This allows you to add new variants later without breaking existing code.

This attribute forces people to have a _ pattern in their matches that will match any items you add later.

#Rust30by30
December 7, 2024 at 8:47 PM
I usually see public reexports at the lib.rs level, with the inner module structure largely hidden. Also note judicious use of non_exhaustive on public structs for api stability
January 15, 2025 at 5:44 PM
things like that generally try to check that it's public knowledge that your type is a ZST. as another comment suggests, rust has a lint for if you use a foreign zst with private fields / # [non_exhaustive] with repr(transparant) as a ZST(it should be a error, but we weren't always smart about this)
December 24, 2025 at 10:27 AM
also I would have made non_exhaustive on structs only require that struct literals and patterns involving that struct require .. when outside of the defining crate (today non_exhaustive is totally broken on structs)
March 29, 2025 at 8:45 PM
Here is the compiler’s logic for checking whether a transparent structure has a legal layout.

github.com/rust-lang/ru...

It seems to have the notion of an unsuited type, which is a non-local ADT with private fields or a `non_exhaustive` attribute, and will lint if you use it as a ZST.
github.com
December 23, 2025 at 2:39 PM
It'd be neat if the next edition made "unit-only" as expressible as "fieldless" with a check against `#[non_exhaustive]` non-tuple empty variants with the repr attached
June 8, 2025 at 4:24 AM
🦀Without `non_exhaustive` attribute

- Let's say we create a library with Menu enum;when you add more variants in the future, it will be a breaking change because users' match statements won't compile

- As library dev, you should bump to next major version (e.g: 1.0.0 to 2.0.0)
September 5, 2025 at 4:09 PM
It's a breaking change to a Rust crate, but the OpenAPI schema it generates is not a breaking change (it's just saying that the server accepts more request bodies than previously)

and the Rust change isn't breaking if the enum is non_exhaustive
September 30, 2025 at 10:22 PM
OneIO v0.21.0 is now available. This release introduces the OneIo client for reusable HTTP configuration, adds custom root certificate support for corporate VPNs, and includes CLI improvements like progress bars and header support. Full changelog: github.com/bgpkit/oneio/releases/tag/v0.21.0
Release v0.21.0 · bgpkit/oneio
Breaking changes OneIoError is now #[non_exhaustive]; match expressions without a wildcard _ arm will fail to compile OneIoBuilder::header() now accepts typed HeaderName/HeaderValue (infallible) i...
github.com
March 28, 2026 at 5:08 AM
okay I'm gonna add the non_exhaustive attribute in a couple of spots and then I'll make the tag.
September 12, 2026 at 4:16 AM
to be clear: I added it to basically every `pub enum`. there's like one that isn't `#[non_exhaustive]` and it's pretty trivial. however, I expect that other tokens and error kinds could be added in the future to accomodate more features, and doing so would be a breaking change if it isn't […]
Original post on transfem.social
transfem.social
September 12, 2026 at 4:21 AM
#[non_exhaustive] alone helps with pattern matching and struct update syntax, but the private unit field fully blocks literal construction.

Great for stable APIs!

More details: doc.rust-lang.org/reference/at...
Type system - The Rust Reference
Press ← or → to navigate between chapters
doc.rust-lang.org
January 28, 2026 at 3:32 PM
Rust library tip: Make your public structs future-proof with #[non_exhaustive] + a private field.

When you might add fields later, this combo prevents direct struct literals, forcing users to use your constructor. Result? You can add fields without breaking existing code.

Example
#rust #rustlang
January 28, 2026 at 3:32 PM
non_exhaustive alone prevents literal construction - in the same reference doc: doc.rust-lang.org/reference/at...

We had this for a while in #AzureSDK for #rustlang but found it to cause more friction than worth it to. When all your data fields are pub anyway, forcing a constructor is pointless.
Type system - The Rust Reference
doc.rust-lang.org
January 28, 2026 at 4:22 PM
Is downgrading a panic to an error a breaking change?
I don’t think there are any really rigorous principles to be had here, but more important principles than not relying on panic behavior are that: * types should have only valid values, and * the return value of a function should be truthful. So, if a `DecryptError` previously represented _only_ “the cyphertext is not authentic”, how does it now also represent “the length is invalid”? If `DecryptError` was (or contained) a `non_exhaustive` `enum`, then there is an obvious possibility of adding a variant to it. But if it is not, then `decrypt` is now returning false information. In general, you should _consciously choose_ whether the set of errors returned by a function is extensible. If it is not, then you must not return errors for new cases unless the new cases fall into the existing description of the error, because the caller might be handling the error with an assumption about what it means. If it is extensible, then turning a panic into an error is IMO usually reasonable, but I would want to be more careful with the original documentation and write that it “ _May_ panic if…”. Even more broadly: when you are doing a “1.0” release, or any one where you care about not having breaking changes in your near future, you should review your API surface — both types and documentation — for over-promising the details of things that you might want to tweak later, and remove such promises.
users.rust-lang.org
January 28, 2025 at 5:22 PM