Skip to content

Releases: obi1kenobi/cargo-semver-checks

v0.38.0

11 Dec 16:24
b9709e6
Compare
Choose a tag to compare

In this release

  • 12 new lints, for a total of 106!
  • Bugfix for packages using the "SemVer trick"
  • Spotlight: Performance via parallelism

This release requires Rust 1.81+ both to install (MSRV) and at runtime.

Spotlight: Performance via parallelism

cargo-semver-checks is on a trajectory of doubling its number of lints every year. But more lints mean more code scanning work to be done! And nobody likes slow tools, so we had to parallelize!

We began taking a serious look at performance in early 2023. Compared to that point ~almost two years ago:

  • Lint checking time has reduced by 20%, in wall-clock terms & measured on the exact same hardware.
  • Yet, we run over 2.5x as many lints in that time!

We've aimed to parallelize as much of the execution of the tool as possible, with help from the rayon library. Today, both the lint execution and the rustdoc indexing steps use rayon to distribute the work across all available cores on your system. In practice, this ~halved linting time on the default GitHub Actions runners (which have only 2 cores), and it has an even bigger impact on more powerful hardware.

Parallelism is one of many tricks we employ to keep cargo-semver-checks fast while it's gaining ever more lints. More on this in future Spotlights!

New lints

Preventing breakage caused by macros, enum discriminants, mutable statics, and generic lifetime parameters:

  • function_like_proc_macro_missing
  • attribute_proc_macro_missing
  • derive_proc_macro_missing
  • derive_helper_attr_removed
  • macro_now_doc_hidden
  • macro_no_longer_exported
  • enum_repr_variant_discriminant_changed
  • enum_discriminants_undefined_non_exhaustive_variant
  • enum_discriminants_undefined_non_unit_variant
  • pub_static_now_mutable
  • type_mismatched_generic_lifetimes
  • trait_mismatched_generic_lifetimes

Thanks to @malenaohl and @orhun for contributing lints to this release!

Bugfix for self-referential crates

Crates that are about to release a new major version often use the "SemVer trick" to make the upgrade process more ergonomic for their users. This involves making the crate list a "future" version of itself as a dependency, which is quite unusual otherwise!

Unfortunately, this leads to having two packages by the same name in the dependency tree, which confused the new feature-scanning code shipped in cargo-semver-checks v0.37. The resulting crash was reported by @jonathanpallant, and is now fixed! Enjoy!

All merged PRs

New Contributors

Full Changelog: v0.37.0...v0.38.0

v0.37.0

05 Dec 03:47
68711cc
Compare
Choose a tag to compare

What's Changed

We shipped support for linting Cargo.toml files for breakage — learn more in the accompanying blog post!

This release requires Rust 1.80+ both to install (MSRV) and at runtime. Future releases will require Rust 1.81+.

All Merged PRs

Full Changelog: v0.36.0...v0.37.0

v0.36.0

18 Oct 14:43
cc74071
Compare
Choose a tag to compare

What's changed

We're debuting a new "Spotlight" section in the release notes! We'll use it to shine a spotlight at aspects of cargo-semver-checks that don't usually get flashy headlines, even though they play a critical role.

In this release:

  • Spotlight: Supporting many Rust versions at once
  • 5 new lints (94 total, who will add lint number 💯?)
  • Performance upgrades
  • Support for comma-separated feature lists

This release requires Rust 1.77+ both to install (MSRV) and at runtime. Future releases will require Rust 1.80+.

Spotlight: Supporting many Rust versions at once

cargo-semver-checks uses the JSON output of Rust's rustdoc tool to analyze your APIs. This JSON format is not stable: between the release of Rust 1.77 on March 21, 2024 and today, we've had 9 mutually-incompatible format versions. That's more than one per month!

Most tools that rely on rustdoc JSON support only a single rustdoc format at a time. The user is required to install the version of the tool that matches the rustdoc format their Rust version provides. This works, but at the cost of pushing extra complexity onto the users.

Instead, we wanted to offer a seamless experience: use reasonably new Rust and newer cargo-semver-checks, and everything just works! Pulling this off required declarative queries, cutting-edge database technology, and the Trustfall query engine, and were described in depth in UA Rust 2024 and RustConf 2024 talks. The talk videos aren't online yet, so please follow along on social media (bsky, Mastodon, Twitter) or by subscribing to blog posts to make sure you don't miss them when they come out ✨

Today's cargo-semver-checks supports all stable Rust versions 1.77-1.82, as well as 1.83 beta and the most recent nightly. Today we set a new record in how many rustdoc formats we support at once! All the maintenance required to make this work is a challenge, and we are grateful to our GitHub Sponsors for supporting this work 💖

New lints

We're now at 94 lints! Who is going to add lint number 💯?

Performance upgrades

In any reasonably well-optimized system, ongoing performance wins usually come in the form of "5% here, 10% there" rather than "10x with this one weird trick." This is now true for cargo-semver-checks as well.

In coordination with the Rust project's T-rustdoc team, and with the tireless efforts of @jalil-salame, cargo-semver-checks users now benefit from:

  • ~6-7% smaller rustdoc JSON files, which consume less disk space to cache and are ~28% faster to load
  • more compact indexes which are ~12% faster to build

This translates to up to ~0.8s time savings for our largest projects, and even more speedup on resource-constrained CI hardware where disk and network I/O are usually much slower than on a desktop machine.

Support for comma-separated feature lists

Previously, our CLI did not support specifying multiple features as a comma-separated list — the following did not work:

cargo semver-checks --features foo,bar

Instead, users had to specify each feature separately, which was quite tedious:

cargo semver-checks --features foo --features bar

Thanks to @dmatos2012, the --features, --baseline-features, and --curent-features CLI options now all support comma-separated lists. What a lovely user experience win!

All Merged PRs

New Contributors

Read more

v0.35.0

03 Sep 16:23
6092892
Compare
Choose a tag to compare

What's changed

In this release:

  • 10 new lints
  • performance upgrades
  • improved bug reporting UX & test infra

This release requires Rust 1.77+ both to install (MSRV) and at runtime.

New lints:

We can now detect whether a trait is sealed or not, unlocking many new lints! "Is this lint sealed" is a tricky question full of edge cases — check out our deep-dive into this feature to learn more!

Additionally, we enabled the trait_no_longer_object_safe lint. It was previously implemented but was disabled while awaiting updated Rust functionality.

We also renamed the variant_marked_non_exhaustive lint to enum_variant_marked_non_exhaustive, for better naming consistency.

Performance upgrades

cargo-semver-checks lints are implemented as database queries. The "database" in our case is rustdoc JSON files, which we load in memory and index for faster lookups. For particularly large crates, this indexing process could take up to 2-3 seconds by itself.

This release cuts the indexing time in half, thanks to the work of @jalil-salame:

Improved bug reporting UX & test infra

Our GitHub bug reporting form requests the diagnostic output of the cargo semver-checks --bugreport command. That output is unwieldy, so it's a bit of a hassle to copy-paste it into the GitHub issue UI.

As of this release, --bugreport will include a URL that pre-fills all the diagnostic information into a GitHub bug report form. Now you can just click the link, and skip the clunky copy-pasting! Thanks to @PedroTurik for shipping this functionality in #862.

@suaviloquence has also been hard at work revamping our test infrastructure so that we can test cargo-semver-checks more thoroughly and in more configurations. He's already shipped a dozen PRs that have made us more confident in our ability to build bigger and bolder features. Skyskrapers cannot stand on wobbly foundations, so keep his hard work in mind while you enjoy the powerful new features we'll be shipping in the months to come!

All Merged PRs

New Contributors

Full Changelog: v0.34.0...v0.35.0

v0.34.0

14 Aug 18:01
158a45a
Compare
Choose a tag to compare

What's Changed

In this release:

  • 3 new lints
  • support for rustdoc format v33

This release requires Rust 1.77+ both to install (MSRV) and at runtime. It also ensures cargo-semver-checks continues to build correctly on Rust 1.80, addressing both the inference-breaking change and the floating-point miscompilation issues in 1.80.0.

New lints

Support for rustdoc format v33

Latest nightly Rust has switched to rustdoc format v33. You'll want to update to this new release if you are relying on nightly.

Implemented across:

All Merged PRs

New Contributors

Full Changelog: v0.33.0...v0.34.0

v0.33.0

24 Jul 21:25
c112aa2
Compare
Choose a tag to compare

What's Changed

In this release:

  • lint configuration
  • a new lint
  • support for rustdoc format v32

PSA: Installing cargo install cargo-semver-checks --no-default-features will no longer work, due to a change in our dependencies that unfortunately had to propagate to our own features as well. Users should update that invocation to cargo install cargo-semver-checks --no-default-features --features gix-reqwest to recover the old behavior. Thanks to @Lorak-mmk for flagging this change!

This release requires Rust 1.74+ both to install (MSRV) and at runtime. This is the last release to support Rust 1.74-1.76; future releases will require Rust 1.77+.

Lint configuration

Thanks to @suaviloquence's hard work as part of our participation in Google Summer of Code, users can now customize the SemVer (major/minor) and severity (deny/warn/allow) levels of cargo-semver-checks lints 🎉

While we've already extensively tested this feature, we know that complex new code often reveals surprises when it first faces the real world. Please kindly report any bugs or reach out in the GSoC project's Zulip if you have questions or concerns.

Read more about this new feature on @suaviloquence's blog: https://blog.mcarr.one/

New lints

Support for rustdoc format v32

Latest nightly Rust has switched to rustdoc format v32, so you'll want to update to this new release if you are relying on nightly. Implemented in #825, and in obi1kenobi/trustfall-rustdoc-adapter#338 by @Xuanwo.

All Merged PRs

New Contributors

Full Changelog: v0.32.0...v0.33.0

v0.32.0

17 Jun 16:17
1d74c88
Compare
Choose a tag to compare

What's Changed

In this release:

  • 3 new lints
  • support for rustdoc format v30
  • performance improvements

This release requires Rust 1.74+ both to install (MSRV) and at runtime.

New lints

Support for rustdoc format v30

Latest nightly Rust has switched to rustdoc format v30, so you'll want to update to this new release if you are relying on nightly. Implemented in #790 and obi1kenobi/trustfall-rustdoc-adapter@65dc425

Performance improvements

@jw013 in #777 figured out a way to improve the performance of a lint that could get quite slow on large codebases. Kudos! 🎉

Google Summer of Code (GSoC)

cargo-semver-checks is participating in Google Summer of Code: @suaviloquence is working on allowing workspaces and packages to customize the SemVer (major/minor/patch) and severity (error/warn/allow) levels of our lints.

Just like how Rustaceans don't enable all clippy lints in all projects, not all SemVer lints are suitable for every circumstance either. This GSoC project will allow us to ship many more lints that we've been holding off on due to their more situational usefulness. Thank you, @suaviloquence!

You can follow this work at @suaviloquence's blog: https://blog.mcarr.one/rust-lint-config/

All Merged PRs

Full Changelog: v0.31.0...v0.32.0

v0.31.0

22 Apr 17:01
44d5e0b
Compare
Choose a tag to compare

What's Changed

In this release:

  • 5 new lints
  • support for rustdoc format v29
  • improved diagnostic messages
  • tightening existing lints to catch more breaking changes
  • new CLI flags for color output
  • improved API if using cargo-semver-checks as a library (breaking changes — see Migration Guide below!)

This release requires Rust 1.74+ both to install (MSRV) and at runtime.

New lints

Support for rustdoc format v29

Latest nightly Rust has switched to rustdoc format v29, so you'll want to update to this new release if you are using a nightly released in the last week or so. Implemented in #769 and obi1kenobi/trustfall-rustdoc-adapter@9fb656a

Improved diagnostic messages

cargo-semver-checks can only semver-check library crates, since binaries have no API surface area to check. But it might not be obvious which crates cargo-semver-checks considered while looking for library crates to check — that's how we get issues like #723. As of this release, we have a better error message here:

error: no crates with library targets selected, nothing to semver-check
note: only library targets contain an API surface that can be checked for semver
note: skipped the following crates since they have no library target: example, other_example

Implemented in #741.

Two other, smaller quality-of-life improvements here are printing which crate features are enabled in --verbose mode (#725), and improving the error message when a crate fails to compile in cases where no features are used (#726).

Huge thanks to @jw013 who has been on a roll here 🙏

Tightening existing lints to catch more breaking changes

cargo-semver-checks has an explicit goal of "zero false-positives" — every lint we emit should point to a real issue deserving of maintainers' attention. (We are decent at this, but not perfect yet. We're working on getting better!)

But many cases aren't clear-cut — some things might be a major breaking change, and the final "yes/no" decision on it depends on many factors. In such cases, cargo-semver-checks is conservative, meaning that we choose to not emit a lint unless absolutely certain. For example:

pub struct MyIterator;

impl MyIterator {
    // We *do not* consider removing this pub method
    // a major breaking change!
    //
    // If removed, *most* callers will seamlessly use
    // the `Iterator` trait's version of the `next()` method.
    pub fn next(&mut self) -> Option<i64> {
        <Self as Iterator>::next(self)
    }
}

impl Iterator for MyIterator {
    type Item = i64;

    fn next(&mut self) -> Option<Self::Item> {
        None
    }
}

In the above example, removing the inherent MyIterator::next() method will not trigger a lint because for most users it won't be breaking. (It could still be breaking for some users though! For example, users who use #![no_implicit_prelude] and don't have the Iterator trait in scope.)

In some cases, we might overshoot and end up being overly conservative: there was a real breaking change, but we failed to emit it because we were too worried about it being a false positive.

This release removes overly conservative cases in the inherent_associated_pub_const_missing and inherent_method_missing lints related to when the impl Trait whose items we're falling back to is #[doc(hidden)] and not public API. The PR has the full details: #763

New CLI flags for color output

The CLI now accepts --color=always/never/auto to match cargo's own behavior. If set, the CLI flag overrides any CARGO_TERM_COLOR env variable that might be set.

Implemented by @suaviloquence in #721

Improved API if using cargo-semver-checks as a library

@suaviloquence took on the work of improving our library APIs:

  • Switched us from termcolor to the newer anstyle crate for our terminal color needs, to match what cargo itself uses. (#737)
  • Allow directing our stdout/stderr to buffers instead of the "real" stdout/stderr (#765)
  • Improve the naming and structural consistency of our API's methods (#765)

Additional thanks go to @pksunkara for the help and advice around switching to anstyle!

@suaviloquence put together this handy migration guide to help library users migrate 👏

Major changes

  • Check::check_release takes a new &mut GlobalConfig parameter, and GlobalConfig now holds log level and color settings.

    • Change:
      let mut check = Check::new(rustdoc);
      check.with_packages(packages)
           .with_log_level(Some(log_level))
           .with_color_choice(Some(termcolor::ColorChoice::Always));
      let result = check.check_release();
    • To:
      let mut config = GlobalConfig::new()
         .set_level(Some(log_level));
      config.set_color_choice(true); // or set_{err,out)_color_choice for finer-grained control
      
      let mut check = Check::new(rustdoc);
      check.with_packages(packages);
      let result = check.check_release(&mut config);
  • Set color choice in one of three ways:

    • Change:
      let choice: termcolor::ColorChoice = ...;
      config = config.set_color_choice(choice);
    • To: one of the three following options, depending on desired granularity
      1. Set global color choice for all crates using the anstream library:
        let choice: anstream::ColorChoice = ...;
        // set *before* creating `GlobalConfig` instance (if using default stdout/stderr)
        // or before calling `GlobalConfig::set_std{out,err}` (if configuring them)
        choice.write_global(); // configures `choice` for all crates using `anstream`
      2. Set whether to use colors for both stdout and stderr in the cargo-semver-checks library:
        let use_colors: bool = ...;
        config.set_color_choice(use_colors);
      3. Set whether to use colors for a specific stream in the cargo-semver-checks library:
        let use_colors_for_stderr: bool = ...;
        let use_colors_for_stdout: bool = ...;
        config.set_err_color_choice(use_colors_for_stderr);
        config.set_out_color_choice(use_colors_for_stdout);
  • config structs (Check, GlobalConfig, PackageSelection) now have a consistent setter convention: pub fn set_[property](&mut self, prop: T) -> &mut Self:

    • note: this does not apply to Check::with_[...]_features() methods as they are toggles vs property setters.
    • Change:
      selection.with_excluded_packages(packages);
      check.with_selection(selection).with_all_features();
    • To:
      selection.set_excluded_packages(packages);
      check.set_package_selection(selection).with_all_features();
    • Change:
      config = config.set_level(level);
    • To:
      config.set_log_level(level); // now takes and returns &mut Self instead of owned Self

New features

  • Users can configure the stdout and stderr streams for cargo-semver-checks to be different from default:
    let stderr: Box<dyn std::io::Write> = Box::new(stderr_buffer);
    config.set_stderr(stderr);

Minor changes

  • #[must_use] added on GlobalConfig::std{err,out}
  • GlobalConfig::shell_print takes an anstyle::Color instead of a termcolor::Color:
    • Change config.shell_print(status, message, termcolor::Color::Red, justified)
    • To config.shell_print(status, message, anstyle::Color::Ansi(anstyle::AnsiColor::Red, justified)
  • To write colors to stdout/stderr, use writeln!(config.stdout(), "{}styled text", anstyle::Style::new().bold().[...]); instead of the termcolor API
  • use GlobalConfig::{out,err}_color_choice() to query whether to print colors for the stdout/stderr stream instead of using GlobalConfig::is_err_tty as a heuristic
  • GlobalConfig::std{out,err} returns an opaque impl Write + '_ type instead of a termcolor::StandardStream

All Merged PRs

Read more

v0.30.0

16 Mar 17:14
84d344b
Compare
Choose a tag to compare

What's Changed

In this release: 7 new lints + assorted UX improvements. This release requires Rust 1.74+ both to install (MSRV) and at runtime.

New lints:

Miscellaneous:

  • Improved output of reproduction command when failing to generate rustdoc JSON, by @obi1kenobi (#676)
  • Improved new-contributor workflow for better compatibility across platforms, by @jw013 (#681, #682, #683)
  • Better description and tests for inherent_method_must_use_added lint, by @pksunkara (#677)
  • Faster compilation times by deduplicating major dependency versions and major dependency version bumps where possible (many PRs, see below)

All Merged PRs

New Contributors

Full Changelog: v0.29.1...v0.30.0

v0.29.1

23 Feb 18:53
3611fd0
Compare
Choose a tag to compare

Just a small maintenance release, to avoid a yanked dependency version that was in our lockfiles. Enjoy!

All Merged PRs

Full Changelog: v0.29.0...v0.29.1