An unused generic parameter should be a warning at the definition site.

733571a
Opened by Felix S Klock II at 2024-12-21 04:50:09

Consider the following code:

fn foo<F>(x: i32) -> i32 { x }

fn bar<'a>(x: i32) -> i32 { x }

fn main() {
    bar(1);
    bar(2);
    foo::<f64>(3);
    foo(4);
    foo(5);
}

Currently, this causes a fatal compiler error at the invocation of foo(4) on line 9, of the form:

error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [--explain E0282]
 --> <anon>:9:5
  |>
9 |>     foo(4);
  |>     ^^^

error: aborting due to previous error

The only way to ever successfully invoke foo is to feed it an explicit type (via the ::<_> syntax as illustrated on line 8).

I suspect in many cases of this error, the actual problem is that the definition of fn foo (and also fn bar) are faulty: since F and 'a are never referenced in the signature nor in the function body, they are irrelevant and should cause a warning via the compiler's linting system.

(A separate issue is that one cannot actually instantiate the 'a parameter to fn bar via the ::<_> syntax, so it seems that its formal lifetime parameter is truly unusable. But things may not remain that way forever, so I think its best to lump both of these cases into the same category.

  1. I actually implemented this lint in #26684! At the time, @alexcrichton was against the lint.

    Seo Sanghyeon at 2016-06-21 10:12:55

  2. I am not sure this would be useful - lints only execute after errors are reported.

    Ariel Ben-Yehuda at 2016-06-21 17:33:36

  3. It looks like the compiler error only happens if the unused parameter is a type. If a lifetime is unused, there is no error or warning. For instance, https://is.gd/aFXcBf and https://play.rust-lang.org/?gist=5368c08fbdcba4efaa8c2e35aa59b429&version=stable&backtrace=0 really should trigger at least a warning.

    Ixrec at 2016-09-20 22:49:29

  4. Dredging up this issue again. I would have liked a lint for unused lifetime parameters to be around for a PR on one of my libraries that removed a lifetime parameter from a struct, but not all of the functions that created it. If the parameter is completely unused, i don't want it appearing in my public API, and thus i would like to have a lint for it so i can keep that from happening.

    QuietMisdreavus at 2017-11-14 00:11:46

  5. bumb This extends to const_generics.

    In the following code, the fact that only reality_check causes a warning (unused_variables) is BAD:

    #![allow(stable_features)]
    #![feature(min_const_generics)]
    
    fn foo<F>(x: i32) -> i32 { x }
    fn bar<'a>(x: i32) -> i32 { x }
    fn baz<const TOTO: i32>(x: i32) -> i32 { x }
    fn reality_check(x: i32, y: i64) -> i32 { x }
    
    fn main() {
        bar(1);
        foo::<f64>(3);
        baz::<5>(4);
        reality_check(99, -1);
    }
    

    playground link

    Arthur Woimbée at 2021-01-27 19:07:47

  6. We should only emit a warning if the generic parater has no bounds, as code like fn is_send<T: Send>() { ... } can be useful.

    Aaron Hill at 2021-01-27 19:19:15

  7. We need a more in-depth discussion on this, something like fn is_send<T: Send>() { ... } could use something like #[allow(unused_generic)], just like I need #[allow(unused_variables)] to define drop myself:

    #[allow(unused_variables)]
    pub fn drop<T>(_x: T) {}
    

    Arthur Woimbée at 2021-01-27 19:42:58

  8. The original report still errors, with a relatively good diagnostic (it could be better):

    error[E0282]: type annotations needed
     --> f71.rs:9:5
      |
    9 |     foo(4);
      |     ^^^ cannot infer type of the type parameter `F` declared on the function `foo`
      |
    help: consider specifying the generic argument
      |
    9 |     foo::<F>(4);
      |        +++++
    

    Esteban Kuber at 2023-08-14 13:43:38