Skip to content

Commit 0cb86cb

Browse files
committed
prevent manual __hash__ with #pyo3(hash)
1 parent 4491fe3 commit 0cb86cb

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

pyo3-macros-backend/src/pyclass.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,14 +1813,14 @@ fn pyclass_hash(
18131813
match options.hash {
18141814
Some(opt) => {
18151815
let mut hash_impl = parse_quote_spanned! { opt.span() =>
1816-
fn __pyo3__hash__(&self) -> u64 {
1816+
fn __pyo3__generated____hash__(&self) -> u64 {
18171817
let mut s = ::std::collections::hash_map::DefaultHasher::new();
18181818
::std::hash::Hash::hash(self, &mut s);
18191819
::std::hash::Hasher::finish(&s)
18201820
}
18211821
};
18221822
let hash_slot =
1823-
generate_default_protocol_slot(cls, &mut hash_impl, &__HASH__, ctx).unwrap();
1823+
generate_protocol_slot(cls, &mut hash_impl, &__HASH__, "__hash__", ctx).unwrap();
18241824
Ok((Some(hash_impl), Some(hash_slot)))
18251825
}
18261826
None => Ok((None, None)),

tests/ui/invalid_pyclass_args.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,15 @@ struct HashWithoutFrozen;
6464
#[derive(Hash)]
6565
struct HashWithoutEq;
6666

67+
#[pyclass(frozen, eq, hash)]
68+
#[derive(PartialEq, Hash)]
69+
struct HashOptAndManualHash {}
70+
71+
#[pymethods]
72+
impl HashOptAndManualHash {
73+
fn __hash__(&self) -> u64 {
74+
todo!()
75+
}
76+
}
77+
6778
fn main() {}

tests/ui/invalid_pyclass_args.stderr

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ error[E0592]: duplicate definitions with name `__pymethod___richcmp____`
8787
|
8888
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)
8989

90+
error[E0592]: duplicate definitions with name `__pymethod___hash____`
91+
--> tests/ui/invalid_pyclass_args.rs:67:1
92+
|
93+
67 | #[pyclass(frozen, eq, hash)]
94+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___hash____`
95+
...
96+
71 | #[pymethods]
97+
| ------------ other definition for `__pymethod___hash____`
98+
|
99+
= note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)
100+
90101
error[E0369]: binary operation `==` cannot be applied to type `&EqOptRequiresEq`
91102
--> tests/ui/invalid_pyclass_args.rs:33:11
92103
|
@@ -168,3 +179,39 @@ help: consider annotating `HashOptRequiresHash` with `#[derive(Hash)]`
168179
57 + #[derive(Hash)]
169180
58 | struct HashOptRequiresHash;
170181
|
182+
183+
error[E0034]: multiple applicable items in scope
184+
--> tests/ui/invalid_pyclass_args.rs:67:1
185+
|
186+
67 | #[pyclass(frozen, eq, hash)]
187+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `__pymethod___hash____` found
188+
|
189+
note: candidate #1 is defined in an impl for the type `HashOptAndManualHash`
190+
--> tests/ui/invalid_pyclass_args.rs:67:1
191+
|
192+
67 | #[pyclass(frozen, eq, hash)]
193+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
194+
note: candidate #2 is defined in an impl for the type `HashOptAndManualHash`
195+
--> tests/ui/invalid_pyclass_args.rs:71:1
196+
|
197+
71 | #[pymethods]
198+
| ^^^^^^^^^^^^
199+
= 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)
200+
201+
error[E0034]: multiple applicable items in scope
202+
--> tests/ui/invalid_pyclass_args.rs:71:1
203+
|
204+
71 | #[pymethods]
205+
| ^^^^^^^^^^^^ multiple `__pymethod___hash____` found
206+
|
207+
note: candidate #1 is defined in an impl for the type `HashOptAndManualHash`
208+
--> tests/ui/invalid_pyclass_args.rs:67:1
209+
|
210+
67 | #[pyclass(frozen, eq, hash)]
211+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
212+
note: candidate #2 is defined in an impl for the type `HashOptAndManualHash`
213+
--> tests/ui/invalid_pyclass_args.rs:71:1
214+
|
215+
71 | #[pymethods]
216+
| ^^^^^^^^^^^^
217+
= note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)

0 commit comments

Comments
 (0)