rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.96k stars 12.68k forks source link

`unused_lifetimes` warning misses unused lifetime #74165

Open bobbobbio opened 4 years ago

bobbobbio commented 4 years ago

I discovered an unused lifetime in my code that the compiler didn't tell me about. I was able to reduce the problem to the following snippet.

#![warn(unused_lifetimes)]

struct Foo<'a>(for<'r> fn(&'r mut Foo<'a>));

impl<'a> Foo<'a> {
    pub fn new() -> Self {
        Self(Self::a)
    }

    pub fn a(&mut self) {}
}

fn main() {
    let f = Foo::new();
    drop(f);
}

The lifetime 'a is unused, but the compiler doesn't complain at all. I confirmed that it still exists on stable 1.44.1 and on nightly 1.46.0.

SNCPlay42 commented 4 years ago

Removing the mut in &'r mut causes the code to fail to compile as expected:

error[E0392]: parameter `'a` is never used
 --> src/main.rs:3:12
  |
3 | struct Foo<'a>(for<'r> fn(&'r Foo<'a>));
  |            ^^ unused parameter
  |
  = help: consider removing `'a`, referring to it in a field, or using a marker such as `std::marker::PhantomData`

The mut causes Foo<'a> to be invariant which is apparently enough to satisfy E0392 - it just checks that there are no unbounded lifetimes. I guess the unused_lifetimes lint assumes E0392 handled any situations like this.

Reduced:

use std::cell::Cell;
pub struct Foo<'a>(Box<Cell<Foo<'a>>>);
Enselic commented 1 year ago

@rustbot label A-lifetimes