0

Using #[non_exhaustive] for Non-exhaustive Structs

Non-exhaustive structs will future-proof our codes by preventing client codes from using Struct expressions. We use Struct expressions to instantiate structs and they’re JSON-like expression in appearance with all fields present. When we update a struct with a new field,  all expressions must be updated to include that field.

The non_exhaustive attribute indicates that a type or variant may have more fields or variants added in the future. It can be applied to structs, enums, and enum variants.

For example, we have a struct Pet with 2 initial fields name and age.

We can instantiate it using a struct expression as follows.

The codes work until we add a new field owner to the struct.

Wouldn’t it be better if we could just disallow struct expressions? We could use #[non_exhaustive]!

Crate-Level-Only Structs

There is one important thing to note about #[non_exhaustive], it only works at the crate level.

Using #[non_exhaustive] for Non-exhaustive Structs

Using #[non_exhaustive] for Non-exhaustive Structs

How then do we instantiate structs? Through factory functions provided by the crate with non-exhaustive structs.

Crate mycrate lib.rs

This crate has the non-exhaustive structs. These are just structs marked with #[non_exhaustive]. The following codes have a struct with 2 public factory functions to instantiate it in the client codes. They are using #[non_exhaustive] on structs which in this case is just Person .

Crate myapp

This crate uses mycrate that has those non-exhaustive structs. Any attempts to use struct expressions to instantiate those structs will fail the building process.

Cargo.toml

main.rs

Output:

Tested with Rust 1.40.0.

Karl San Gabriel

Karl San Gabriel

Professional Software Developer