A look at the new feature of Rust 1.64
Rust 1.64 has arrived today and this version will impact hundreds of projects of all types around the web.
The reason for this is that it comes with a key feature to any project divided into a plethora of different crates. This feature is the workspace inheritance, which will allow us to share fields like version numbers or metadata fields between crates. The Cargo.toml
file has started to follow the DRY principle, at last.
Say goodbye to copy-pasting licenses and authors
One of the first things anyone does when they create a new crate is to open the manifest of a previous one and copy all the sections that are common between both — even if they are in the same workspace.
For example, in the repository that I use to showcase the code examples, you can see that I used to have the same authors
key in each crate. Now I can take out all that duplication. How? First, making the root Cargo.toml
to be like this:
[package]
name = "sotoestevez_medium"
version = "0.1.0"
[workspace]
members = ["add_trait", "beginning_tips", "generify_with_compiler_errors", "modules", "scoped_threads" ]
[workspace.package]
edition = "2021"
authors = ["Soto Estévez <ricardo@sotoestevez.dev>"]
description = "Demos of the articles at https://medium.com/@sotoestevez"
documentation = "https://medium.com/@sotoestevez"
readme = "./README.md"
homepage = "https://www.sotoestevez.dev"
repository = "https://github.com/kriogenia/medium"
license = "MIT OR Apache-2.0"
In this new version, under [workspace.package]
you can define some of the keys of the package section to be declared as the workspace default.
This will allow the workspace crates to opt-in and inherit those sections that is the same and otherwise would be duplicated (which, in this example, are all the crates of the repository as you see in workspace.members
).
Now, to make use of those defaults we just need to invoke them into the other manifests. For example, this is add_trait/Cargo.toml
now:
[package]
name = "add_trait"
version = "0.1.0"
edition.workspace = true
authors.workspace = true
description = "Dissecting Rust Traits to Learn Their Secrets"
documentation = "https://betterprogramming.pub/dissecting-rust-traits-to-learn-their-secrets-839845d3d71e"
homepage.workspace = true
repository.workspace = true
license.workspace = true
The manifest of add_trait
will now inherit the values that we did set up in the root for the keys that we brought with {key}.workspace
like edition
or authors
. See also how we can just ignore those that we don’t want to bring like readme
, as this crate won’t have one; or description
, which is different and we are overriding.
With this new manifest, all the projects will use the same edition always and updates like changing the license won’t have to be manually updated in each one.
Keep versions in sync
But there’s another thing that we can do with this new inheritance that will be key in business projects. This is using the inheritance to grant the synchronism between dependencies. To do this we can follow the same approach as we did with [package]
but using [workspace.dependencies]
and the typical dependency declaration (but we can’t use optional
here).
For example, adding this to the root Cargo.toml
will set workspace default versions and features to these three dependencies:
[... rest of the manifest ]
[workspace.dependencies]
num = { version = "0.4", default-features = false }
vector2d = "2.2"
rand = "0.8.5"
And now, at generify_with_compiler_errors
we can use those dependencies with the workspace version and features declaring them in the manifesto-like in the following example:
[package]
name = "generify_with_compiler_errors"
version = "0.1.0"
edition = "2021"
authors.workspace = true
[dependencies]
num = { workspace = true, default-features = true }
vector2d.workspace = true
[dev-dependencies]
rand = { workspace = true, features = [ "log" ] }
See how we declared vector2d
the same way it’s in the workspace but how we did override the num
dependency as this crate needs to make use of the default features, we just use the same version. This crate doesn’t use rand
but I added it to show how you can declare features on top of those declared and bring the dependencies not only in [dependencies]
but also in [dev-dependencies]
and [build-dependencies]
.
And that’s all for today, if you can check the whole new Rust version you can do it here, and to see the actual code in work you can find it as always in the repository linked below.
GitHub - kriogenia/medium: Repository to host the examples used on my Medium posts You can't perform that action at this time. You signed in with another tab or window. You signed out in another tab or…github.com
See you again in Rust 1.65, we’ll be looking at those long-awaited GATs.