Skip to content

Unable to provide a Clippy suppression attribute for a variable's type #202

@yeputons

Description

@yeputons

Consider the following example:

use http::Uri;
use std::collections::HashSet;
use lazy_static::lazy_static;

fn main() {
    // Clippy thinks that `Uri` has interior mutability and yields a warning
    let _a: HashSet<Uri> = HashSet::new();
    // Warning is suppressed
    #[allow(clippy::mutable_key_type)]
    let _b: HashSet<Uri> = HashSet::new();
}

lazy_static! {
    // Trying to suppress the warning
    #[allow(clippy::mutable_key_type)]
    static ref _C: HashSet<Uri> = HashSet::new();
}

if I run clippy on it, I get:

    Checking playground v0.0.1 (/playground)
warning: mutable key type
 --> src/main.rs:7:5
  |
7 |     let _a: HashSet<Uri> = HashSet::new();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(clippy::mutable_key_type)]` on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type

warning: mutable key type
  --> src/main.rs:16:20
   |
16 |     static ref _C: HashSet<Uri> = HashSet::new();
   |                    ^^^^^^^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type

warning: mutable key type
  --> src/main.rs:13:1
   |
13 | / lazy_static! {
14 | |     // Trying to suppress the warning
15 | |     #[allow(clippy::mutable_key_type)]
16 | |     static ref _C: HashSet<Uri> = HashSet::new();
17 | | }
   | |_^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type
   = note: this warning originates in the macro `__lazy_static_internal` (in Nightly builds, run with -Z macro-backtrace for more info)

warning: `playground` (bin "playground") generated 3 warnings
    Finished dev [unoptimized + debuginfo] target(s) in 0.43s

So, the warning is not suppressed on _a and is suppressed on _b as expected. However, the attribute on _C does nothing. Moreover, two warnings are yielded, not just one.

Looking at the expansion (courtesy of IntelliJ's Rust plugin, so may be off):

#[allow(missing_copy_implementations)]
#[allow(non_camel_case_types)]
#[allow(dead_code)]
#[allow(clippy::mutable_key_type)]
struct _C {
    __private_field: (),
}
#[doc(hidden)]
static _C: _C = _C { __private_field: () };
impl ::lazy_static::__Deref for _C {
    type Target = HashSet<Uri>;
    fn deref(&self) -> &HashSet<Uri> {
        #[inline(always)]
        fn __static_ref_initialize() -> HashSet<Uri> { (HashSet::new()) }

        #[inline(always)]
        fn __stability() -> &'static HashSet<Uri> {
            static LAZY: ::lazy_static::lazy::Lazy<HashSet<Uri>> = ::lazy_static::lazy::Lazy::INIT;
            LAZY.get(__static_ref_initialize)
        }
        __stability()
    }
}
impl ::lazy_static::LazyStatic for _C {
    fn initialize(lazy: &Self) {
        let _ = &**lazy;
    }
}

It seems that the attribute is attached to the struct _C, but warnings are actually emitted by some code in the macro. I'm not really sure what is the proper fix here: I suspect some attribute should really go to the struct _C, some should go to the static _C, and some (like allow(clippy::mutable_key_type) should be scattered in the macro.

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