rust-lang / rust

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

Unused generic parameter E0392 not emitted in recursive type that is behind Cell #92561

Closed Noratrieb closed 2 years ago

Noratrieb commented 2 years ago

When you have an unused lifetime (or type) parameter, it is a hard error. If you "use" that parameter by having a recursive type, rustc still notices that it's unused and gives the error. But if that recursion goes through Cell (also works with RefCell), the error is not emitted and the program works fine.

Maybe this should be a diagnostics issue, but I put this under bug since it causes programs to compile that shouldn't under the normal rules.

I tried this code:

playground

use std::cell::Cell;

struct GivesAnError<'a> {
    same: Box<GivesAnError<'a>>,
}

#[derive(Debug, Default)]
struct NoError<'a> {
    same: Box<Cell<NoError<'a>>>,
}

I expected to see this happen: E0392, because the lifetime is actually not used

Instead, this happened: No error, and the program compiled

Meta

This happens on the latest nightly-2022-01-04 on the playground

Aaron1011 commented 2 years ago

This is a very subtle issue. The compiler is not actually checking if the lifetime 'a get used - it's checking if has its variance inferred. With Box<GivesAnError<'a>>, there are no constraints placed in the variance of 'a (Box is covariant). However, with Box<Cell<NoError<'a>>>, Cell ends up forcing 'a to be invariant, allowing the code to compile.

SNCPlay42 commented 2 years ago

Duplicate of #74165

Noratrieb commented 2 years ago

Ah, so the normal error is not really a lint but the compiler being forced to abort, that makes sense. I guess it makes sense to close this, since it's a duplicate, I couldn't find the duplicate when searching for duplicates 😅