Skip to content

Conversation

@fischeti
Copy link
Contributor

@fischeti fischeti commented Jan 11, 2026

Warning collection

This PR collects the current warnings system into a monolithic diagnostic::Warnings enum, which has the following benefits:

  • Make it much easier to keep warning codes coherent which are also used to suppress warnings
  • Allows for easier reuse of warnings without duplicating the warning message
  • Consistent formatting of Warning messages
  • Additional help messages to guide the user to solution to the warning.

Suppression handling improvements

Additionally, the current warning and error suppression system has been improved a bit. A global resp. static Diagnostics handler now takes care of suppression. It is initialized in the beginning with the user defined suppressed warnings. This cleans up the code since suppress_warnings does not need to be passed around anymore, and whether a warning is suppressed is checked automatically behind the scenes when a Warning is emitted. Further, the Diagnostic handler keeps track of emitted warnings and deduplicates them to avoid redundant warnings. It not only differentiates between the type of warning but also it's content (e.g. SomeWarningAbougPkg for pkg1 is treaded as different than SomeWarningAboutPkg for pkg2).

Warning formatting

The new formatting of warnings and help messages is shown below:

warning: This is a warning without a code and without a help message.

warning[W03]: This is a warning with code "W03" and without help message
 
warning: This is a warning without a code, but a help message
 ╰─› help: This is the help message
 
warning[W02]: This is a warning with code "W02" and a help message
 ╰─› help: This is the help message
 
warning[W06]: This is a warning with code "W06" and multiple help messages (if separated by "\n")
 ├─› help: This is the first message
 ╰─› help: This is the second message

(in reality the warnings are also colored properly)

New crates adoption

Two new crates were adopted to reduce boilerplate code and derive warning/help messages, error codes and severity from procedural macros:

enum Warning {
    #[error("This is the warning message containing {some_data}")]
    #[diagnostic(code(W42), severity(warning), help("Fix something in {some_data}"))]
    SomeWarning { some_data: String }
}

miette

This crate uses the #[diagnostic] macro to implement traits for the specified enumeration variants that allows it to call help(), code() and severity() on an enum variant. miette can do a lot more and is mostly used for nice annotations of source code. In the case of Bender this is less relevant since it is not a compiler that reads source code. It could in theory be used to annotate wrong Bender.yml files, but this is a bit overkill at the moment, and our current YAML parser does not return positional information of fields in the source.

thiserror

The second crate uses the #[error] macro to derive the Display trait for the warning message. At the moment, we are not using thiserror to its full extend. It also implements automatic Error conversion and chaining, which will be implemented in a separate PR to make the review easier.

TODO:

  • Some warnings currently have the same warning code. This is not a problem for miette, but suppression is impacted potentially.

@fischeti fischeti changed the title Consolidate warnings and warning suppression + deduplicate Consolidate warnings, suppression and deduplication Jan 11, 2026
@fischeti fischeti force-pushed the fischeti/diagnostics branch 3 times, most recently from b9e1d7f to 505e4d8 Compare January 12, 2026 22:08
@fischeti fischeti force-pushed the fischeti/diagnostics branch from 505e4d8 to 584251b Compare January 14, 2026 13:42
error: Move W04 to `Warnings`

error: Move W05 to `Warnings`

error: Move W06 to `Warnings`

error: Move W07 to `Warnings`

error: Move W08 to `Warnings`

error: Move W09 to `Warnings`

error: Move W10 to `Warnings`
error: Move W11 to `Warnings`

error: Move W12 to `Warnings`

error: Move W13 to `Warnings`

error: Move W14 to `Warnings`

error: Deduplicate W15/W01 warnings

error: Move W15 to `Warnings`
error: Move W17 to `Warnings`
error: Move W19 to `Warnings`

error: Move W20 to `Warnings`

error: Move W21 to `Warnings`

error: Move W22 to `Warnings`

error: Move W23 to `Warnings`

error: Move W24 to `Warnings`

error: Move W30 to `Warnings`

error: Move W31 to `Warnings`

error: Move W32 to `Warnings`

error: Move uncoded Warning to `Warnings`
@fischeti fischeti force-pushed the fischeti/diagnostics branch from e6decd3 to b8a2940 Compare January 14, 2026 20:04
@fischeti fischeti force-pushed the fischeti/diagnostics branch from b8a2940 to b7601c1 Compare January 14, 2026 20:36
@fischeti fischeti marked this pull request as ready for review January 14, 2026 20:41
@fischeti fischeti requested a review from micprog January 14, 2026 20:41
fischeti and others added 2 commits January 15, 2026 09:57
The `fancy` feature is mainly used for code annotation, that we don't
use at the moment. Since we implement our own warning formatter, we
don't actually require this feature
Copy link
Member

@micprog micprog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some minor things, but overall LGTM! I really like the updated output and the cleaner handling of suppressing warnings!

There are some warnings that should actually be help information for an error, which are currently noted as TODOs. Thanks for doing this, I think it's best addressed in an upcoming PR.

Comment on lines 203 to 217
// TODO(fischeti): This is part of an error, not a warning. Should be converted to an Error.
#[error("SSH key might be missing.")]
#[diagnostic(
code(W07),
help("Please ensure the url is correct and you have access to the repository.")
)]
UrlMaybeIncorrect,

// TODO(fischeti): This is part of an error, not a warning. Should be converted to an Error.
#[error("Revision {} not found in repository {}.", fmt_version!(.0), fmt_pkg!(.1))]
#[diagnostic(
code(W08),
help("Check that the revision exists in the remote repository or run `bender update`.")
)]
RevisionNotFound(String, String),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we convert this to a single warning, with a flag passed that enables the ssh key information? Ultimately we will want to put this into the help information of an error, but a warning is what we have for now...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good idea. It is now controlled by a is_ssh field. Turns out you can put arbitrary code in the derive macro for the help message.

Comment on lines 182 to 193
// TODO(fischeti): Why are there two W06 variants?
#[error("Dependency {} in checkout_dir {} is not a git repository. Setting as path dependency.", fmt_pkg!(.0), fmt_path!(.1.display()))]
#[diagnostic(
code(W06),
help("Use `bender clone` to work on git dependencies.\nRun `bender update --ignore-checkout-dir` to overwrite this at your own risk.")
)]
NotAGitDependency(String, PathBuf),

// TODO(fischeti): Why are there two W06 variants?
#[error("Dependency {} in checkout_dir {} is not in a clean state. Setting as path dependency.", fmt_pkg!(.0), fmt_path!(.1.display()))]
#[diagnostic(code(W06), help("Use `bender clone` to work on git dependencies.\nRun `bender update --ignore-checkout-dir` to overwrite this at your own risk."))]
DirtyGitDependency(String, PathBuf),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this was due to the warnings being closely related or an error on my part. Happy to adjust if needed, but IMO we can also keep as-is. Why is the formatting different for the two?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine by me to keep it as is, just wanted to double check. The automattic formatting for derive macros is a bit random sometimes. I aligned the formatting now.

DepPathMissing { pkg: String, path: PathBuf },
}

#[cfg(test)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move these tests to a separate file in the tests directory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can, this is the structure suggested by the Rust book, but I don't have a strong opinion on that.

src/cli.rs Outdated
if suppressed_warnings.contains("all") || suppressed_warnings.contains("Wall") {
suppressed_warnings.extend((1..24).map(|i| format!("W{:02}", i)));
}
let warn_config_loaded = !suppressed_warnings.contains("W02");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still needed with the updated warning system, where these warning outputs are suppressed the diagnostics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, good point. I simplified it now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants