Skip to content

Misplaced error on ambiguous Borrow impl #70980

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

Closed
Nadrieril opened this issue Apr 10, 2020 · 2 comments
Closed

Misplaced error on ambiguous Borrow impl #70980

Nadrieril opened this issue Apr 10, 2020 · 2 comments
Labels
C-bug Category: This is a bug.

Comments

@Nadrieril
Copy link
Member

I tried this code (playground):

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
struct Label(String);

impl std::borrow::Borrow<str> for Label {
    fn borrow(&self) -> &str {
        self.0.as_ref()
    }
}
impl<'a> From<&'a str> for Label {
    fn from(s: &'a str) -> Self {
        Label(s.to_string())
    }
}

use std::collections::HashMap;

fn main() {
    let foo: HashMap<Label, ()> = Default::default();
    let _ = foo.get(&"k".into());
    let _ = foo.iter().map(|(k, v): (&Label, _)| ()).count();
}

I initially didn't have the Borrow impl, so the foo.get line was unambiguous. When I added the impl, that line became ambiguous, because the .into() could mean into Label or into String. I expected the compiler to report that; instead, I got a nonsensical error on the following line:

error[E0283]: type annotations needed for `(&Label, &())`
  --> src/main.rs:20:29
   |
20 |     let _ = foo.iter().map(|(k, v): (&Label, _)| ()).count();
   |                             ^^^^^^ consider giving this closure parameter the explicit type `(&Label, &())`, where the type parameter `Label` is specified
   |
   = note: cannot satisfy `Label: std::borrow::Borrow<_>`

Note how it mentions Borrow even though nothing needs Borrow on that line. Note also how it asks for a concrete type even though it is already concrete.

Meta

I originally got the error on stable but it fails in the playground on nightly too.

@Nadrieril Nadrieril added the C-bug Category: This is a bug. label Apr 10, 2020
@Nadrieril
Copy link
Member Author

Minimized a bit:

use std::borrow::Borrow;

struct Label(String);

impl Borrow<str> for Label {
    fn borrow(&self) -> &str {
        self.0.as_ref()
    }
}
impl<'a> From<&'a str> for Label {
    fn from(s: &'a str) -> Self {
        Label(s.to_string())
    }
}

fn get<Q: ?Sized>(k: &Q)
where
    Label: Borrow<Q>,
{
}

fn iter(f: impl FnMut(Label)) {}

fn main() {
    get(&"k".into());
    iter(|k: Label| ());
}

(play)

I thought it was specific to HashMap and Borrow but it doesn't look like it anymore. It fails even when there is no link between the two lines at all. There's something about using the same type twice where one is ambiguous somehow.

@Nadrieril
Copy link
Member Author

Ah, this is duplicate with #70082 and #69455 that I hadn't found before. Closing in favor of those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

1 participant