Skip to content

Invalid suggestion already set #108712

@Zannick

Description

@Zannick

I tried this code (playground):

pub trait Ctx: Clone + Eq + Debug {
type Loc: Loc;
}

pub trait Accessible {
    type Context<'a>: Ctx;
    fn can_access<'a>(&self, ctx: &Self::Context<'a>) -> bool;
}

pub trait Id: Copy + Clone + Debug + Eq + Hash + Ord + PartialOrd {}

pub trait Loc: Accessible {
    type LocId: Id;
}

// error
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum History<T>
where T: Ctx
{
    Visit(<<T as Ctx>::Loc as Loc>::LocId),
    Action(<<T as Ctx>::Loc as Loc>::LocId),
}

#[derive(Copy, Clone, Default, Eq, PartialEq)]
pub struct HSlice<'a, T>
where T: Ctx {
    slice: &'a [History<T>],
}
impl<'a, T> Hash for HSlice<'a, T> where T: Ctx {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        (*self.slice).hash(state);
    }
}

I expected either:

  1. code compiles (because History<T> implements Hash and thus [History<T>] implements Hash)
  2. a useful error message tells me to require T: Hash
  3. some other useful suggestion

Instead, this happened:

rust suggests deriving Hash on History<T> which has already done so.

error[E0599]: the method `hash` exists for slice `[History<T>]`, but its trait bounds were not satisfied
  --> src/lib.rs:37:23
   |
23 | pub enum History<T>
   | ------------------- doesn't satisfy `History<T>: Hash`
...
37 |         (*self.slice).hash(state);
   |                       ^^^^ method cannot be called on `[History<T>]` due to unsatisfied trait bounds
   |
   = note: the following trait bounds were not satisfied:
           `History<T>: Hash`
           which is required by `[History<T>]: Hash`
help: consider annotating `History<T>` with `#[derive(Hash)]`
   |
23 | #[derive(Hash)]

I've included in the playground link an alternate derivation of Hash with the useful version of the error:

// Variant
#[derive(Copy, Clone, Default, Eq, PartialEq)]
pub struct VSlice<'a, T>
where T: Ctx {
    slice: &'a [History<T>],
}
impl<'a, T> Hash for VSlice<'a, T> where T: Ctx {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.slice.iter().for_each(|v| v.hash(state));
    }
}

error:

error[E0599]: the method `hash` exists for reference `&History<T>`, but its trait bounds were not satisfied
  --> src/lib.rs:49:42
   |
23 | pub enum History<T>
   | ------------------- doesn't satisfy `History<T>: Hash`
...
49 |         self.slice.iter().for_each(|v| v.hash(state));
   |                                          ^^^^ method cannot be called on `&History<T>` due to unsatisfied trait bounds
   |
note: trait bound `T: Hash` was not satisfied
  --> src/lib.rs:22:45
   |
22 | #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
   |                                             ^^^^ unsatisfied trait bound introduced in this `derive` macro
   = note: the following trait bounds were not satisfied:
           `History<T>: Hash`
           which is required by `&History<T>: Hash`
help: consider restricting the type parameter to satisfy the trait bound
   |
24 | where T: Ctx, T: Hash
   |             +++++++++
help: consider annotating `History<T>` with `#[derive(Hash)]`
   |
23 | #[derive(Hash)]
   |

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`C-bugCategory: This is a bug.D-incorrectDiagnostics: A diagnostic that is giving misleading or incorrect information.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.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

    Issue actions