Skip to content

Fix: unused_variables warnings were silently suppressed#448

Open
usmanovbf wants to merge 1 commit intodtolnay:masterfrom
usmanovbf:feat_unused_vars
Open

Fix: unused_variables warnings were silently suppressed#448
usmanovbf wants to merge 1 commit intodtolnay:masterfrom
usmanovbf:feat_unused_vars

Conversation

@usmanovbf
Copy link

Description

This PR fixes #446, resolving the issue where unused_variables warnings were silently suppressed for fields in structs and enums deriving thiserror::Error.

The Problem

Previously, the Display trait implementation generated by the macro unpacked all fields of a given variant and applied a global #[allow(unused_variables)] directive to the entire match block. While this successfully prevented compiler warnings for fields not referenced in the #[error("...")] format string, it had the unintended side effect of masking legitimate dead code and unused variable warnings within the user's own data structures.

The Solution

Instead of relying on a blanket allow directive, this PR implements selective variable binding:

  1. Format String Parsing: During the attribute parsing phase (impl/src/fmt.rs), the macro now scans the format string and its arguments to track exactly which fields are referenced (including .field and .0 syntax). These are collected in a new used_field_names set.
  2. Selective Pattern Generation: When building the match arm patterns (impl/src/expand.rs), fields that are present in used_field_names are bound to their normal identifiers. Fields that are not referenced in the format string are bound to the wildcard pattern (e.g., field_name: _ for named fields, or simply _ for unnamed fields).
  3. Restoring the Lint: With the unused fields correctly ignored via _, the unused_variables exception has been safely removed from the #[allow(...)] attribute over the match block.

As a result, the Rust compiler's standard static analysis is restored for the user's types.

Testing

Added a UI test (tests/ui/unused_variables.rs) with #![deny(unused_variables)]. This ensures via trybuild that the compiler correctly emits errors for unused fields, safeguarding against future regressions of this behavior.

Thank you for your time reviewing this!

@usmanovbf
Copy link
Author

@dtolnay there are test in tests/test_display.rs, e.g.

#[test]
fn test_braced_unused() {
#[derive(Error, Debug)]
#[error("braced error")]
struct Error {
extra: usize,
}
assert("braced error", Error { extra: 0 });
}
where some variables are already unused.
I propose to introduce some migrational period for developers who use thiserror to get rid of the unused variable errors from their code, e.g. for 6 months. And for now it should be enabled by special feature, e.g. features = ["unused_variables"]
If you agree, I will supress the errors in tests/test_display.rs by enabling this feature by default in order to make tests green and throwing a warning with the migration period disclaimer for developers

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.

No unused field warnings are produced on enums deriving thiserror::Error

1 participant