Skip to content

Clippy complains about unused assignments in the Encode derive macro in nightly. #89

Description

@ReCore-sys

A project I'm working on uses nightly and recently clippy has started throwing some errors regarding unused assignments. I am currently using nightly version 1.92.0 (367fd9f21 2025-10-15) and the following snippet of code is causing linting errors:

#[derive(Encode, Decode, Clone, Eq, PartialEq, Debug)]
pub enum PaletteType {
    Single(VarInt),
    Indirect {
        bits_per_block: u8,
        data: Vec<i64>,
        palette: Vec<VarInt>,
    },
    Direct {
        bits_per_block: u8,
        data: Vec<i64>,
    },
}

with the following error from running cargo clippy:

warning: value assigned to `bits_per_block` is never read
  --> src\lib\world\src\chunk_format.rs:61:9
   |
61 |         bits_per_block: u8,
   |         ^^^^^^^^^^^^^^
   |
   = help: maybe it is overwritten before being read?
   = note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default

warning: value assigned to `data` is never read
  --> src\lib\world\src\chunk_format.rs:62:9
   |
62 |         data: Vec<i64>,
   |         ^^^^
   |
   = help: maybe it is overwritten before being read?

warning: value assigned to `palette` is never read
  --> src\lib\world\src\chunk_format.rs:63:9
   |
63 |         palette: Vec<VarInt>,
   |         ^^^^^^^
   |
   = help: maybe it is overwritten before being read?

warning: value assigned to `bits_per_block` is never read
  --> src\lib\world\src\chunk_format.rs:66:9
   |
66 |         bits_per_block: u8,
   |         ^^^^^^^^^^^^^^
   |
   = help: maybe it is overwritten before being read?

warning: value assigned to `data` is never read
  --> src\lib\world\src\chunk_format.rs:67:9
   |
67 |         data: Vec<i64>,
   |         ^^^^
   |
   = help: maybe it is overwritten before being read?

The fields are 100% being read and written to in other parts of the codebase, even in the same file. Removing the Encode derive macro causes these linting errors to disappear. We are using Encode/Decode in many other places in the codebase but as far as I know, this is the only instance where we use it on enums with fields, the rest are either structs or plain enums.
Here is an expanded version of the macro: https://gist.github.com/ReCore-sys/50285d4eb94a6cd52bb9b9fffadb510c
This has only cropped up recently and since we try to stay on the latest version of nightly, this is likely an issues with bleeding-edge clippy having breaking changes, not your code but I'd still appreciate it if this could be looked into.
I do want to note that this appears to only be an issue with the Encode derive macro, removing/adding the Decode one doesn't fix the linting errors in any way.
I'm happy to link the full codebase if needed but I don't want to come across as advertising my project.

Activity

  1. finnbear commented on Oct 17, 2025

    @finnbear
    Member

    Thanks! Out of curiosity, I tried cargo expand on your type:

    $ cargo expand
        Checking bitunused v0.1.0 (/home/finnb/tmp/bitunused)
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.03s
    
    #![feature(prelude_import)]
    #[prelude_import]
    use std::prelude::rust_2024::*;
    #[macro_use]
    extern crate std;
    struct VarInt;
    pub enum PaletteType {
        Single(VarInt),
        Indirect {
            bits_per_block: u8,
            data: Vec<i64>,
            palette: Vec<VarInt>,
        },
        Direct {
            bits_per_block: u8,
            data: Vec<i64>,
        },
    }
    const _: () = {
        impl bitcode::__private::Encode for PaletteType {
            type Encoder = PaletteTypeEncoder;
        }
        #[allow(non_snake_case)]
        pub struct PaletteTypeEncoder {
            variants: bitcode::__private::VariantEncoder<3usize>,
            Single_f0: <VarInt as bitcode::__private::Encode>::Encoder,
            Indirect_bits_per_block: <u8 as bitcode::__private::Encode>::Encoder,
            Indirect_data: <Vec<i64> as bitcode::__private::Encode>::Encoder,
            Indirect_palette: <Vec<VarInt> as bitcode::__private::Encode>::Encoder,
            Direct_bits_per_block: <u8 as bitcode::__private::Encode>::Encoder,
            Direct_data: <Vec<i64> as bitcode::__private::Encode>::Encoder,
        }
        impl ::core::default::Default for PaletteTypeEncoder {
            fn default() -> Self {
                Self {
                    variants: Default::default(),
                    Single_f0: Default::default(),
                    Indirect_bits_per_block: Default::default(),
                    Indirect_data: Default::default(),
                    Indirect_palette: Default::default(),
                    Direct_bits_per_block: Default::default(),
                    Direct_data: Default::default(),
                }
            }
        }
        impl bitcode::__private::Encoder<PaletteType> for PaletteTypeEncoder {
            fn encode(&mut self, v: &PaletteType) {
                #[allow(unused_imports)]
                use bitcode::__private::Buffer as _;
                #[allow(unused_variables)]
                self.variants.encode(&match v {
                    PaletteType::Single(f0) => 0u8,
                    PaletteType::Indirect {
                        bits_per_block,
                        data,
                        palette,
                    } => 1u8,
                    PaletteType::Direct {
                        bits_per_block,
                        data,
                    } => 2u8,
                });
                match v {
                    PaletteType::Single(f0) => {
                        let __additional = ::core::num::NonZeroUsize::MIN;
                        self.Single_f0.reserve(__additional);
                        self.Single_f0.encode(f0);
                    }
                    PaletteType::Indirect {
                        bits_per_block,
                        data,
                        palette,
                    } => {
                        let __additional = ::core::num::NonZeroUsize::MIN;
                        self.Indirect_bits_per_block.reserve(__additional);
                        self.Indirect_data.reserve(__additional);
                        self.Indirect_palette.reserve(__additional);
                        self.Indirect_bits_per_block.encode(bits_per_block);
                        self.Indirect_data.encode(data);
                        self.Indirect_palette.encode(palette);
                    }
                    PaletteType::Direct {
                        bits_per_block,
                        data,
                    } => {
                        let __additional = ::core::num::NonZeroUsize::MIN;
                        self.Direct_bits_per_block.reserve(__additional);
                        self.Direct_data.reserve(__additional);
                        self.Direct_bits_per_block.encode(bits_per_block);
                        self.Direct_data.encode(data);
                    }
                }
            }
            fn encode_vectored<'__v>(&mut self, i: impl Iterator<Item = &'__v PaletteType> + Clone)
            where
                PaletteType: '__v,
            {
                #[allow(unused_imports)]
                use bitcode::__private::Buffer as _;
                for t in i {
                    self.encode(t);
                }
            }
        }
        impl bitcode::__private::Buffer for PaletteTypeEncoder {
            fn collect_into(&mut self, out: &mut bitcode::__private::Vec<u8>) {
                self.variants.collect_into(out);
                self.Single_f0.collect_into(out);
                self.Indirect_bits_per_block.collect_into(out);
                self.Indirect_data.collect_into(out);
                self.Indirect_palette.collect_into(out);
                self.Direct_bits_per_block.collect_into(out);
                self.Direct_data.collect_into(out);
            }
            fn reserve(&mut self, __additional: ::core::num::NonZeroUsize) {
                self.variants.reserve(__additional);
            }
        }
    };
    pub fn main() {}

    Note that we already have #[allow(unused_variables)] on the match statement that does generate unused variables in the patterns, for ease of implementation. These variables never have a value assigned to them after their declaration.

    I was able to reproduce this issue, but only on the original source, not after running cargo expand, which surfaced a disjoint set of unused warnings.

    I then fixed all the warnings by adding a few #[allow(unused...)] attributes in the code in PR #90. We'll merge it at some point in the future.

  2. ReCore-sys commented on Oct 17, 2025

    @ReCore-sys
    Author

    Amazing, thanks a bunch for the quick work. Would there be a timeframe on getting this merged? Wondering whether it's worth waiting a few days for the merge or downloading the fixed branch as a local crate to the project while we wait.

  3. finnbear commented on Oct 17, 2025

    @finnbear
    Member

    Sure :)

    I merged my PR but, prior to releasing a new version of the crate on crates.io, we want to merge #84 and review #88 (which may take weeks, possibly months).

    There may be workarounds you can use. You could try adding #![allow(unused_assignments)] at the top of your source file.

    Alternatively, unless you publish your crate on crates.io, you can add this to your Cargo.toml (keeping your existing dependency):

    [patch.crates-io]
    bitcode = { git = "https://github.com/SoftbearStudios/bitcode" }
  4. ManevilleF commented on Dec 17, 2025

    @ManevilleF

    @finnbear I think it would be good to make a small 0.6.8 release with #90 , all users of Rust 1.92 get those warnings

  5. marked Linter issue with enums #95 as a duplicate of this issue on Dec 17, 2025
  6. finnbear commented on Dec 17, 2025

    @finnbear
    Member

    bitcode@0.6.8 is available. Please confirm that it fixes this :)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions