Skip to content

Commit

Permalink
prevent manual __hash__ with #pyo3(hash)
Browse files Browse the repository at this point in the history
  • Loading branch information
Icxolu committed May 31, 2024
1 parent 4491fe3 commit 0cb86cb
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 2 deletions.
4 changes: 2 additions & 2 deletions pyo3-macros-backend/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1813,14 +1813,14 @@ fn pyclass_hash(
match options.hash {
Some(opt) => {
let mut hash_impl = parse_quote_spanned! { opt.span() =>
fn __pyo3__hash__(&self) -> u64 {
fn __pyo3__generated____hash__(&self) -> u64 {
let mut s = ::std::collections::hash_map::DefaultHasher::new();
::std::hash::Hash::hash(self, &mut s);
::std::hash::Hasher::finish(&s)
}
};
let hash_slot =
generate_default_protocol_slot(cls, &mut hash_impl, &__HASH__, ctx).unwrap();
generate_protocol_slot(cls, &mut hash_impl, &__HASH__, "__hash__", ctx).unwrap();
Ok((Some(hash_impl), Some(hash_slot)))
}
None => Ok((None, None)),
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/invalid_pyclass_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,15 @@ struct HashWithoutFrozen;
#[derive(Hash)]
struct HashWithoutEq;

#[pyclass(frozen, eq, hash)]
#[derive(PartialEq, Hash)]
struct HashOptAndManualHash {}

#[pymethods]
impl HashOptAndManualHash {
fn __hash__(&self) -> u64 {
todo!()
}
}

fn main() {}
47 changes: 47 additions & 0 deletions tests/ui/invalid_pyclass_args.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,17 @@ error[E0592]: duplicate definitions with name `__pymethod___richcmp____`
|
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0592]: duplicate definitions with name `__pymethod___hash____`
--> tests/ui/invalid_pyclass_args.rs:67:1
|
67 | #[pyclass(frozen, eq, hash)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___hash____`
...
71 | #[pymethods]
| ------------ other definition for `__pymethod___hash____`
|
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0369]: binary operation `==` cannot be applied to type `&EqOptRequiresEq`
--> tests/ui/invalid_pyclass_args.rs:33:11
|
Expand Down Expand Up @@ -168,3 +179,39 @@ help: consider annotating `HashOptRequiresHash` with `#[derive(Hash)]`
57 + #[derive(Hash)]
58 | struct HashOptRequiresHash;
|

error[E0034]: multiple applicable items in scope
--> tests/ui/invalid_pyclass_args.rs:67:1
|
67 | #[pyclass(frozen, eq, hash)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `__pymethod___hash____` found
|
note: candidate #1 is defined in an impl for the type `HashOptAndManualHash`
--> tests/ui/invalid_pyclass_args.rs:67:1
|
67 | #[pyclass(frozen, eq, hash)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl for the type `HashOptAndManualHash`
--> tests/ui/invalid_pyclass_args.rs:71:1
|
71 | #[pymethods]
| ^^^^^^^^^^^^
= note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0034]: multiple applicable items in scope
--> tests/ui/invalid_pyclass_args.rs:71:1
|
71 | #[pymethods]
| ^^^^^^^^^^^^ multiple `__pymethod___hash____` found
|
note: candidate #1 is defined in an impl for the type `HashOptAndManualHash`
--> tests/ui/invalid_pyclass_args.rs:67:1
|
67 | #[pyclass(frozen, eq, hash)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: candidate #2 is defined in an impl for the type `HashOptAndManualHash`
--> tests/ui/invalid_pyclass_args.rs:71:1
|
71 | #[pymethods]
| ^^^^^^^^^^^^
= note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)

0 comments on commit 0cb86cb

Please sign in to comment.