rust-lang / rust-lang/rust

Confusing error message when using Borrow'd keys in Hashmap

Open
#133,555 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
use std::borrow::Borrow;
use bumpalo::Bump;
use std::collections::HashSet;

#[derive(PartialEq, Eq, Hash)]
struct Board; 

#[derive(PartialEq, Eq, Hash)]
struct TreeNode<'a> {
    state: Board, 
    foo: &'a ()
}

impl Borrow<Board> for TreeNode<'_> {
    fn borrow(&self) -> &Board {
        &self.state
    }
}

// Reduced for clarity
fn new_from_bump<'b>(state: Board, alloc: &'b Bump, cache: &HashSet<&'b TreeNode>) {
        cache.contains(&state);
}
Current output
error[E0277]: the trait bound `&TreeNode<'_>: Borrow<Board>` is not satisfied
   --> src/lib.rs:22:24
    |
22  |         cache.contains(&state);
    |               -------- ^^^^^^ the trait `Borrow<Board>` is not implemented for `&TreeNode<'_>`
    |               |
    |               required by a bound introduced by this call
    |
note: required by a bound in `HashSet::<T, S>::contains`
   --> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/collections/hash/set.rs:671:12
    |
669 |     pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
    |            -------- required by a bound in this associated function
670 |     where
671 |         T: Borrow<Q>,
    |            ^^^^^^^^^ required by this bound in `HashSet::<T, S>::contains`
help: consider removing the leading `&`-reference
    |
22  -         cache.contains(&state);
22  +         cache.contains(state);
    |
Rationale and extra context

I'm not confident I'm interpreting this correctly, but I think this error message is misleading because the signature of contains implies that the Borrow implementation needs to be on the type Q=Board. Additionally, taking the suggestion of removing the & leads to an error because the parameter needs to be a &Q and there's no valid type for Q that makes &Q equal to Board.

Changing the Borrow impl to instead be for &TreeNode does work, but looking at the docs, this isn't consistent with the general concept of the trait or the other examples in stdlib so I feel like it's not the right answer. If it is the right answer, the provided error message doesn't do anything to point me in that direction.

Rust Version
❯ rustc --version --verbose
rustc 1.81.0 (eeb90cda1 2024-09-04)
binary: rustc
commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c
commit-date: 2024-09-04
host: x86_64-pc-windows-msvc
release: 1.81.0
LLVM version: 18.1.7

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the reduced HashSet::contains example and inspect the emitted E0277 diagnostic, including its help suggestion. Trace how the Borrow bound and suggestion are selected; done means the diagnostic accurately explains the reference-level mismatch and no longer suggests an invalid fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.