Rust, Software Development

Using #[non_exhaustive] for Non-exhaustive Structs

Rust Lang

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 two 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 two 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.

You Might Also Like