Skip to content

pybind: Add __hash__ to all binding types #627

Open
deustis wants to merge 5 commits into
google:masterfrom
deustis:deustis/fix_hash_bindings
Open

pybind: Add __hash__ to all binding types #627
deustis wants to merge 5 commits into
google:masterfrom
deustis:deustis/fix_hash_bindings

Conversation

@deustis
Copy link
Copy Markdown
Contributor

@deustis deustis commented May 13, 2026

In Python 3, defining __eq__ without __hash__ implicitly sets __hash__ = None, making the type unhashable. All seven affected types raised:

TypeError: unhashable type: 's2geometry_bindings.S1Angle'

Adds __hash__ to S1Angle, S1Interval, R1Interval, R2Point, R2Rect, S2LatLng, and S2Point using absl::Hash on their underlying values.

In Python 3, defining __eq__ without __hash__ sets __hash__ = None,
making the type unhashable. All seven affected types raised:

  TypeError: unhashable type: 's2geometry_bindings.S1Angle'

Adds __hash__ to S1Angle, S1Interval, R1Interval, R2Point, R2Rect,
S2LatLng, and S2Point using absl::Hash on their underlying values.
@deustis deustis changed the title pybind: Add __hash__ to all binding types that define __eq__ pybind: Add __hash__ to all binding types May 13, 2026
@deustis deustis marked this pull request as ready for review May 13, 2026 04:49
Copy link
Copy Markdown
Member

@jmr jmr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar for the rest of the classes.

Comment thread src/python/r2point_bindings.cc Outdated
return self /= v;
}, py::arg("v"), "In-place division by scalar")
.def("__hash__", [](const R2Point& self) {
return absl::Hash<std::pair<double, double>>()(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no AbslHashValue for vector? This should be absl::HashOf(self), I think.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posted by Claude: R2Point is BasicVector<double, 2> which already has AbslHashValue defined in vector.h, so absl::HashOf(self) works there. For the types that were missing it (R1Interval, S1Angle, S1Interval, R2Rect), I've added AbslHashValue free functions to their headers and updated all binding files to use absl::HashOf(self) uniformly.

@deustis
Copy link
Copy Markdown
Contributor Author

deustis commented May 13, 2026

Updated R2Point, S2Point, and S2LatLng to use absl::HashOf(self) — those three already have AbslHashValue defined (BasicVector and s2latlng.h). That change is pushed.

The remaining four — S1Angle, S1Interval, R1Interval, R2Rect — don't have AbslHashValue. For those, should we add AbslHashValue to their C++ headers so we can use the same pattern, or drop __hash__ from their Python bindings entirely?

These types already define AbslHashValue, so absl::HashOf(self) is
more idiomatic than manually extracting and hashing fields.
@deustis deustis requested a review from jmr May 13, 2026 15:54
@deustis
Copy link
Copy Markdown
Contributor Author

deustis commented May 19, 2026

@jmr, just checking on this PR? (Also #625 and #626)

Comment thread src/python/r1interval_bindings.cc Outdated
.def(py::self != py::self, "Return true if two intervals do not contain the same set of points")
.def("__hash__", [](const R1Interval& self) {
return absl::Hash<std::pair<double, double>>()(
std::make_pair(self.lo(), self.hi()));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add AbslHashValue for R1Interval and other types missing it

Copy link
Copy Markdown
Contributor Author

@deustis deustis May 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: added AbslHashValue free functions to r1interval.h, s1angle.h, s1interval.h, and r2rect.h, then updated all four binding files to use absl::HashOf(self) uniformly.

deustis added 3 commits May 20, 2026 17:31
Use AbslHashValue free functions in the respective headers so that the
Python bindings can call absl::HashOf(self) uniformly instead of
manually assembling a std::pair/tuple over the component fields.
…2Rect

Uses absl::VerifyTypeImplementsAbslHashCorrectly to confirm the newly
added AbslHashValue functions satisfy the hash contract.
.def("__truediv__", [](const S1Angle& a, const S1Angle& b) -> double {
return a / b;
}, py::arg("other"), "Divide two angles, returning a scalar ratio")
.def(py::self += py::self, "In-place addition")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be merged/rebased? it looks like more than hash

Copy link
Copy Markdown
Contributor Author

@deustis deustis May 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was intentional, based on the other PR thread:
#626 (comment)

We decided to remove bindings for in-place operators because they make hashing unstable. I rolled those changes into this PR (updated the PR description just now).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep them separate. This PR is "add hash".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Moved the in-place operator removal to #629

@deustis deustis force-pushed the deustis/fix_hash_bindings branch from a2e57e6 to 040dd76 Compare May 22, 2026 15:46
@deustis deustis requested a review from jmr May 22, 2026 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants