Skip to content

Type inference asks for annotations that are already present #69214

Closed
@alecmocatta

Description

@alecmocatta
Contributor
use std::convert::TryInto;

fn main() {
    let _: usize = Some(0usize).map(|host: usize| 0usize).unwrap() + 0usize.try_into().unwrap();
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0284]: type annotations needed for `usize`
 --> src/main.rs:4:38
  |
4 |     let _: usize = Some(0usize).map(|host: usize| 0usize).unwrap() + 0usize.try_into().unwrap();
  |                                      ^^^^ consider giving this closure parameter a type
  |
  = note: cannot resolve `<usize as std::ops::Add<_>>::Output == usize`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0284`.
error: could not compile `playground`.

To learn more, run the command again with --verbose.

Activity

added
A-diagnosticsArea: Messages for errors, warnings, and lints
C-bugCategory: This is a bug.
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Feb 16, 2020
Coder-256

Coder-256 commented on Feb 17, 2020

@Coder-256
Contributor

That diagnostic is a bit misleading. This works:

Playground

use std::convert::TryInto;

fn main() {
    let _: usize = Some(0usize).map(|host: usize| 0usize).unwrap()
        + (0usize.try_into() as Result<usize, _>).unwrap();
}

I guess the compiler can't figure out the type of the 2nd addend, and by extension, what type you expect from try_into(). I think in this case, I think it's true that usize is the only type that satisfies T for both usize: Add<T, Output = usize> and usize: TryInto<T>. However, I am not convinced that the compiler should be expected to deduce this, especially because it is possible to implement both of these traits on usize for some other T (due to rust-lang/rfcs#2451). For example:

Playground

use std::{convert::TryInto, ops::Add};

struct Foo;

impl Add<Foo> for usize {
    type Output = usize;
    
    fn add(self, rhs: Foo) -> Self::Output {
        unimplemented!()
    }
}

impl TryInto<Foo> for usize {
    type Error = ();
    
    fn try_into(self) -> Result<Foo, Self::Error> {
        unimplemented!()
    }
}

In other words, I think it is expected that this would not compile, and the problem is the misleading diagnostic.

alecmocatta

alecmocatta commented on May 9, 2020

@alecmocatta
ContributorAuthor

Closing as this is fixed in latest nightly, I suspect by #71960. Thanks @estebank!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-inferenceArea: Type inferenceC-bugCategory: This is a bug.T-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

        Participants

        @alecmocatta@jonas-schievink@Coder-256

        Issue actions

          Type inference asks for annotations that are already present · Issue #69214 · rust-lang/rust