Skip to content

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

Closed
@Susurrus

Description

@Susurrus

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)

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`C-enhancementCategory: An issue proposing an enhancement or a PR with one.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.E-mediumCall for participation: Medium difficulty. Experience needed to fix: Intermediate.P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions