Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unclear errors with type annotations on functions instead of their traits #42226

Closed
Susurrus opened this issue May 25, 2017 · 5 comments · Fixed by #81042
Closed

Unclear errors with type annotations on functions instead of their traits #42226

Susurrus opened this issue May 25, 2017 · 5 comments · Fixed by #81042
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-enhancement Category: An issue proposing an enhancement or a PR with one. D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Susurrus
Copy link
Contributor

Susurrus commented May 25, 2017

A common problem I run into is that I add type annotations to into where it should really be on the Into trait instead. The error messages given for this are not helpful because they don't suggest adding type annotations to the Trait and then using UFCS instead of method syntax.

So what happens is that I write my code thinking rustc can figure out the types, but it fails. A rough example is as follows (on play.rust-lang.org):

struct Y {}

impl Y {
    pub fn new() -> Self {
        Y{}
    }
}

impl Into<u32> for Y {
    fn into(self) -> u32 {
        0u32
    }
}

fn some_func(d: u32) {}

fn main() {
    let y = Y::new();
    let x = y.into() * 512u32;
    some_func(x)
}

So I think that rustc could infer all the types here, but it fails with:

error[E0283]: type annotations required: cannot resolve `Y: std::convert::Into<_>`
  --> <anon>:20:15
   |
20 |     let x = y.into() * 512u32;
   |               ^^^^

Okay, that's fine, I can add some type annotations then. Now I only frequently work with type annotations on functions, so forgetting that the type annotation for Into is on the trait and not the function, I replace the let x... line above with let x = y.into::<u32>() * 512u32; (on play.rust-lang.org) and get the following error:

error[E0035]: does not take type parameters
  --> <anon>:20:15
   |
20 |     let x = y.into::<u32>() * 512u32;
   |               ^^^^ called with unneeded type parameters

Another thing I end up trying is to explicitly specify the type of x by changing the let x... line to let x: u32 = y.into() * 512u32;, but you get the same initial error (E0283).

So a correct solution to this problem is to add the type annotations to Into like so let x = Into::<u32>::into(y) * 512u32;

So my proposal here is twofold: 1) allow type inference to work for this example (which is quite reminiscent of code that I write) and 2) improve both E0283 and E0035.

For point 2, I think it would be possible to detect this exact situation and specify the correct solution.If the compiler sees type annotations on a function that doesn't have any, check the trait it's from and see if the trait itself takes type parameters. You could ignore the number of parameters specified to make this simpler and change E0035 to have help text at the bottom like:

error[E0035]: `into()` does not take type parameters
  --> <anon>:20:15
   |
20 |     let x = y.into::<u32>() * 512u32;
   |               ^^^^ called with unneeded type parameters
   |
   = help: Did you mean to specify type parameters to the trait `Into` instead?
           Possibly try instead `Into::<u32>::into(y)`

Something similar can be done for E0283. I don't know if there's a way that the compiler could tell if a type annotation on the output would work or if it has to be an input type annotation on the right-hand side, but I think defaulting to specifying the type directly would be the right solution anyways. Again I think the heuristic should be if there is a function that doesn't have a type annotation but its trait does then it should add help text to the error similar to that for E0035:

error[E0283]: type annotations required: cannot resolve `Y: std::convert::Into<_>`
  --> <anon>:20:15
   |
20 |     let x = y.into() * 512u32;
   |               ^^^^
   |
   = help: Specify the type for `y.into()` like `Into::<XXX>::into(y)`, substituting the desired
           type for XXX.

Note: These examples were run on rustc 1.17.0 (56124baa9 2017-04-24)

@QuietMisdreavus QuietMisdreavus added A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools A-diagnostics Area: Messages for errors, warnings, and lints labels May 25, 2017
@sampersand
Copy link

I've been running across roughly the same issue, but when writing my unit tests. Writing trait annotations constantly makes it much too verbose:

struct Wrapper(String);
impl AsRef<str> for Wrapper {
   fn as_ref(&self) -> &str { &self.0 }
}

#[test]
fn test_me(){
   let foo_wrap = Wrapper(String::from("foo"));
   let bar = String::from("bar");
   // assert_ne!(foo_wrap.as_ref(), bar.as_ref()); // Doesn't compile
   assert_ne!(AsRef::<str>::as_ref(&foo_wrap), AsRef::<str>::as_ref(&bar)); // does work but is too verbose
}

@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 26, 2017
@steveklabnik steveklabnik added the P-medium Medium priority label Aug 30, 2017
@steveklabnik steveklabnik added the E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. label May 29, 2018
@oli-obk
Copy link
Contributor

oli-obk commented May 24, 2019

Triage: no change in diagnostics, tagging as needs suggestions

@oli-obk oli-obk added the A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` label May 24, 2019
@estebank
Copy link
Contributor

estebank commented Jan 22, 2020

Triage: no real change and the new span is not correct. Current output:

error[E0283]: type annotations needed for `Y`
  --> src/main.rs:20:15
   |
19 |     let y = Y::new();
   |         - consider giving `y` a type
20 |     let x = y.into() * 512u32;
   |               ^^^^ cannot infer type for struct `Y`
   |
   = note: cannot resolve `Y: std::convert::Into<_>`

It should suggest let x = <Y as Into<u32>>::into(y) * 512u32;

@estebank estebank added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. and removed A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools labels Jan 22, 2020
@estebank
Copy link
Contributor

Current output:

error[E0283]: type annotations needed
  --> src/main.rs:20:15
   |
20 |     let x = y.into() * 512u32;
   |             --^^^^--
   |             | |
   |             | cannot infer type for struct `Y`
   |             this method call resolves to `T`
   |
   = note: cannot satisfy `Y: std::convert::Into<_>`

@sasurau4
Copy link
Contributor

I'll try it. @rustbot claim

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix` C-enhancement Category: An issue proposing an enhancement or a PR with one. D-invalid-suggestion Diagnostics: A structured suggestion resulting in incorrect code. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants