Skip to content

Unexpected warning about unused assignment in Rust 1.92 and newer #151514

Closed

Description

@Tiwalun

Code

I tried this code, which is using the docsplay crate:

#[derive(docsplay::Display)]
pub enum DocsplayError {
    /// Use field a: {a}, but not b.
    A { a: usize, b: usize },
    /// Generic error in a tuple
    B(usize),
}

I expected to see this happen:

This code should compile, and no warning should be shown.

Instead, this happened:

I get a warning about an unused assignment:

warning: value assigned to `b` is never read
 --> src/lib.rs:4:19
  |
4 |     A { a: usize, b: usize },
  |                   ^
  |
  = help: maybe it is overwritten before being read?
  = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

This is unexpected, because there is no visible assignment anywhere. The expanded code for the macro looks like this:

// Expanded version of above code

pub enum DocsplayErrorExpanded {
    /// Use field a: {a}, but not b.
    A { a: usize, b: usize },
    /// Generic error in a tuple
    B(usize),
}
impl ::core::fmt::Display for DocsplayErrorExpanded {
    fn fmt(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        #[allow(unused_imports)]
        use ::docsplay::{DisplayToDisplayDoc, PathToDisplayDoc};
        #[allow(unused_variables)]
        match self {
            Self::A { a, b } => formatter.write_fmt(format_args!(
                "Use field a: {0}, but not b.",
                (&(a)).__displaydoc_display(),
            )),
            Self::B(_0) => formatter.write_fmt(format_args!("Generic error in a tuple")),
        }
    }
}

There is #[allow(unused_variables)], which means that the unused field b does not trigger that warning, but it is unexpected that the unused_assignments warning is triggered.

Version it worked on

It most recently worked on: 1.91

Version with regression

rustc --version --verbose:

rustc 1.92.0 (ded5c06cf 2025-12-08)
binary: rustc
commit-hash: ded5c06cf21d2b93bffd5d884aa6e96934ee4234
commit-date: 2025-12-08
host: x86_64-unknown-linux-gnu
release: 1.92.0
LLVM version: 21.1.3

Also seems to happen on the latest nighly,, rustc 1.95.0-nightly (eda76d9d1 2026-01-21).

Backtrace

Backtrace

<backtrace>

Activity

  1. added
    C-bugCategory: This is a bug.
    regression-untriagedUntriaged performance or correctness regression.
    on Jan 22, 2026
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Jan 22, 2026
  3. eggyal commented on Jan 22, 2026

    @eggyal
    Contributor

    searched nightlies: from nightly-2025-06-01 to nightly-2026-01-22
    regressed nightly: nightly-2025-10-13
    searched commit range: be0ade2...2300c2a
    regressed commit: ff6dc92

    bisected with cargo-bisect-rustc v0.6.11

    Host triple: x86_64-unknown-linux-gnu
    Reproduce with:

    cargo bisect-rustc --start=2025-06-01 
  4. Jarcho commented on Jan 23, 2026

    @Jarcho
    Contributor

    The relevant output of the derive is approximately:

    match self {
        Self::A { a, b } => {
            write!(f, "Use field a: {a}, but not b")
        },
        ...
    } 
    

    The span of the b identifier in the pattern is the same as the span in the declaration so it's not considered to be from an expansion. I haven't checked what the b pattern has as a span.


    A roughly equivalent macro_rules macro would define the simple case as approximately Self::$var_name { $($field_names),* } => { write!(f, $msg) }. Note that this ends up with the lint span on $field_names, but I think that's some macro_rules span magic.

  5. eggyal commented on Jan 23, 2026

    @eggyal
    Contributor

    @rustbot label:+L-unused_assignments

  6. eggyal commented on Jan 23, 2026

    @eggyal
    Contributor

    Since there is actually an unused assignment (albeit one that also triggers the unused_variable lint), I'm not sure whether it's correct (and therefore should also be emitted when expanded/not generated by a proc-macro) or not (and therefore should not be emitted when generated by a proc-macro)?

    unused_assignments should not be triggered here.

    /// Second, report unused assignments that do not correspond to initialization.
    /// Initializations have been removed in the previous loop reporting unused variables.
    fn report_unused_assignments(self) {

    @rustbot claim
    @rustbot label:-regression-untriaged +regression-from-stable-to-stable

  7. added
    regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
    and removed
    regression-untriagedUntriaged performance or correctness regression.
    on Jan 23, 2026
  8. apiraino commented on Jan 23, 2026

    @apiraino
    Contributor

    Assigning priority (discussion on #t-compiler/prioritization/alerts > #151514 Unexpected warning about unused assignment in Rust … @ 💬)

    regressed in #142390

    cc @cjgillot

    @rustbot label -I-prioritize +P-high -needs-triage

  9. added
    P-highHigh priority
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Jan 23, 2026
  10. added a commit that references this issue on Jan 25, 2026
    9415853
  11. added 3 commits that reference this issue on Jan 26, 2026
    f336b94
    7297107
    b05aa77
  12. added a commit that references this issue on Jan 27, 2026
    f1af745
  13. added 2 commits that reference this issue on Mar 19, 2026
    9cdb011
    f71a5a0
  14. added a commit that references this issue on Mar 27, 2026
    8d42314
  15. added a commit that references this issue on Aug 7, 2026
    3c8fa98
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.L-unused_assignmentsLint: unused_assignmentsP-highHigh priorityregression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions