MSRV, build.rs and clippy

As workaround for the continued lack of cargo support for this seemingly basic feature, I and some others have been embedding Minimum Supported Rust Version (MSRV) checks directly into build.rs. Here are some updates since the linked post.

Clippy

The embedded build.rs approach has the advantage of zero additional build dependencies, but as its code is intended to work on rustc 1.0.0, clippy has been a nagging (no pun intended) issue. I've now found a solution to this I want to share, in case its useful to others in similar circumstances.

From Rust Report Card - Get a badge for your Rust open source project - #9 by dekellum

I skimmed the configuration section of clippy's README and quickly tried all of these variants, in order:

#![allow(clippy::all)]
#![allow(clippy)]
#![feature(custom_inner_attributes)] // hmmm
#![clippy::msrv = "1.0.0"]

All of the above cause compile failures (via cargo build), with older versions of rustc, and/or fail to silence newish clippy. Just yesterday, I finally stumbled upon the following undocumented syntax, which has the advantage of both silencing newish clippy, and purely as a bonus, not breaking the build! I though I'd share in case others are using a similar approach. Insert at top of build.rs:

#![cfg_attr(feature = "cargo-clippy", allow(clippy::all))]

Anyone know if/where feature cargo-clippy is documented? This is all I can find.

Having avoided pages of useless clippy lints for my intentionally old-styled build.rs, it would still be nice to take advantage of clippy's MSRV awareness for the main source code of these projects. There is a safer alternative way to encode an MSRV for clippy, which I missed on first skim of the README, that doesn't actually require an unstable nightly feature of rust 1.30.0, or require any code changes that could possibly break the build. In a 3rd location, besides build.rs and README.md, add a clippy.toml file in each crate directory, with:

msrv = "1.39.0"

At least for recent clippy lints on recent rust versions, this avoids lints and suggestions which aren't available alternatives on the current MSRV. I suspect I'll occasionally delete this file locally, in order to get a preview, and perhaps more reasons to increase MSRV (in a subsequent minor release of course, I'm not a barbarian).

Clippy's 2021 roadmap includes a section on configuration with further links. Too bad there still isn't an MSRV attribute in Cargo.toml that all associated tools could, just, use.

Related RFCs

RFC 2494 (tracking issue) was accepted and merged, but now 30 months later has yet to be implemented in a usable form. In early 2020 cargo#7801 attempted a more usable implementation but was closed as too ambitious or controversial. Subsequently, cargo#8037 implements only a field in Cargo.toml behind a nightly feature gate that will effectively guarantee it remains unused. This was just merged today, and seems a long way from being a workable replacement for even what myself and others are currently doing with build.rs. This missing feature is frequently touted as the final solution, to get cargo's active help in avoiding patch upgrades which have MSRV increases beyond the currently running toolchain. Until something usable lands, some of us continue with build.rs MSRV checks and even manual version constraints as below, as a poor substitute for better release practices with our direct or indirect dependencies:

# A tempfile dependency, max transitive for MSRV 1.39.0
# https://github.com/Stebalien/tempfile/issues/120
remove_dir_all = { version=">=0.5.0, <0.5.3", optional=true, default-features=false }

My current intuition is that even a fully baked RFC 2494 implementation is an inferior substitute for the ecosystem adopting more mature release practices, including ≥1.0.0 releases of mature core crates, and avoiding MSRV and other minor dependency upgrades in patch releases. While RFC 2494 in cargo could help, other resolver changes, like collapsing duplicates where possible and by default, would also help.

RFC 2523 (tracking issue) was accepted and merged. The #[cfg(version(1.x.y))] syntax was AFAICT implemented as an unstable feature in 1.45.0. The linked tracking issue includes, some IMO bizarre design machinations regarding the interpretation of nightly (or beta) rust version numbers, and its not clear to me when or if this will eventually stabilize in a practical/usable way. In any case, its not a substitute for a dependency resolution aware RFC 2494.

Regarding the hard won cfg_attr syntax for disabling newish clippy, without breaking primordial MSRV build.rs, I want to give credit where credit is due. The hint for this syntax was from this closed issue:

Regarding RFC 2494, see also recent comments on tracking issue, including my own.

1 Like