Rust: detect when "unconstrained type parameters" could be provided explicitly to a fn call

Created on 21 Feb 2017  ·  3Comments  ·  Source: rust-lang/rust

Building on https://github.com/rust-lang/rust/pull/39361, we might want to consider when users should add explicit type parameters to a fn call. I am imagining an example like this:

fn foo<T>() { }

fn main() {
    foo();
}

It'd be nice to suggest that the user write foo::<T> for some explicit T. This will require a bit of thought:

When do we want to suggest this in preference to annotating a local variable? I'd prefer to attach the annotation on the local variable, but maybe not if the type of the local variable is some complex thing that mentions the uninferred type deeply inside of it, whereas annotating the function would allow us to specify the uninferred type directly.

An example:

fn foo<T>() -> Option<T> { }

fn main() {
    let x = foo();
}

Should we suggest labeling x: Option<T> or foo::<T>? This case is borderline, but if you replace Option with some more complex type it tilts the balance further.

What do we do when the fn takes many types, and we know them partially? We side-stepped the problem before of what to do when we have some information but not all. But it feels like here it may be more important. An example:

fn foo<T, U>() -> T { }

fn main() {
    let x: i32 = foo();
}

Here we know T, but not U. Should we suggest foo::<_, XXX>? How do we phrase the XXX to indicate to the user that this is the thing they need to provide?

cc @cengizIO -- interesting in pursuing?

cc @estebank @jonathandturner -- thoughts on how to phrase?

A-diagnostics C-enhancement E-needs-mentor T-compiler WG-compiler-errors

Most helpful comment

Current output:

error[E0282]: type annotations needed
  --> $DIR/xxx.rs:xx:xx
   |
14 |     let x: i32 = foo();
   |                  ^^^ cannot infer type for `U`
   |
   = note: type annotations or generic parameter binding required

Some options:

error[E0282]: type annotations needed
  --> $DIR/xxx.rs:xx:xx
   |
14 |     let x: i32 = foo();
   |                  ^^^ cannot infer type for `U`
   |
   = note: type annotations or generic parameter binding required
   = note: generic parameter `U` needs to be specified for foo::<T, U>()
error[E0282]: type annotations needed
  --> $DIR/xxx.rs:xx:xx
   |
14 |     let x: i32 = foo();
   |                  ^^^ cannot infer type for `U`
   |                  |
   |                  you can specify the generic parameter here using `foo::<_, U>()`
   |
   = note: generic parameter `U` needs to be specified for `fn foo::<T, U>() -> T`
error[E0282]: type annotations needed
  --> $DIR/xxx.rs:xx:xx
   |
14 |     let x: i32 = foo();
   |                  ^^^ cannot infer type for `U` in `fn foo<T, U>() -> T`
   |                  |
   |                  specify `U` using `foo::<_, U>()`
   |

All 3 comments

Hello @nikomatsakis

I'll be working on this.

Thanks again!

Current output:

error[E0282]: type annotations needed
  --> $DIR/xxx.rs:xx:xx
   |
14 |     let x: i32 = foo();
   |                  ^^^ cannot infer type for `U`
   |
   = note: type annotations or generic parameter binding required

Some options:

error[E0282]: type annotations needed
  --> $DIR/xxx.rs:xx:xx
   |
14 |     let x: i32 = foo();
   |                  ^^^ cannot infer type for `U`
   |
   = note: type annotations or generic parameter binding required
   = note: generic parameter `U` needs to be specified for foo::<T, U>()
error[E0282]: type annotations needed
  --> $DIR/xxx.rs:xx:xx
   |
14 |     let x: i32 = foo();
   |                  ^^^ cannot infer type for `U`
   |                  |
   |                  you can specify the generic parameter here using `foo::<_, U>()`
   |
   = note: generic parameter `U` needs to be specified for `fn foo::<T, U>() -> T`
error[E0282]: type annotations needed
  --> $DIR/xxx.rs:xx:xx
   |
14 |     let x: i32 = foo();
   |                  ^^^ cannot infer type for `U` in `fn foo<T, U>() -> T`
   |                  |
   |                  specify `U` using `foo::<_, U>()`
   |

This note in particular makes my eyes glaze over:

   = note: type annotations or generic parameter binding required

Let's definitely remove that one. :)

Was this page helpful?
0 / 5 - 0 ratings