GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — __hash__ to slot_wrapper by youknowone · Pull Request #6480 · RustPython/RustPython

Conversation

@youknowone

@youknowone youknowone commented Dec 24, 2025 •
edited by coderabbitai Bot
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Refactor
    • Improved internal organization of slot function handling to enhance code maintainability and consistency.
    • Strengthened integration of hash function support in class initialization.

✏️ Tip: You can customize this high-level summary in your review settings.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@coderabbitai

coderabbitai Bot commented Dec 24, 2025 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR introduces a SlotFunc enum to type-erase slot functions, replacing direct InitFunc usage. The enum supports Init and Hash variants with a unified call() method for dispatch. It updates PySlotWrapper to use SlotFunc, adds __hash__ slot wrapper creation in class registration, and removes the public __hash__ method from the Hashable trait.

Changes

Cohort / File(s) Summary
SlotFunc Type Abstraction
crates/vm/src/builtins/descriptor.rs
Introduces pub enum SlotFunc with Init(InitFunc) and Hash(HashFunc) variants; adds Debug impl and pub fn call() method to uniformly dispatch to wrapped functions. Updates PySlotWrapper.wrapped field from InitFunc to SlotFunc and replaces all direct function calls with SlotFunc::call() at call sites.
Slot Wrapper Registration
crates/vm/src/class.rs
Imports SlotFunc from descriptor module; wraps init_func as SlotFunc::Init(init_func) for __init__ wrappers; introduces conditional creation of __hash__ slot wrappers using SlotFunc::Hash(hash_func) when hash slot exists and is not hash_not_implemented.
Trait Simplification
crates/vm/src/types/slot.rs
Removes public __hash__() method from Hashable trait; hash access is now exclusively via SlotFunc::Hash wrappers registered in extend_class().

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • RustPython/RustPython#4884 — Both PRs modify slot-wrapper code; this PR extends the wrapper mechanism by introducing SlotFunc type-erasure and new __hash__ wrapper support.

Poem

🐰 Slot functions dance in enums bright,
Init and Hash in type-safe flight,
A wrapper calls with unified grace,
No more confusion, all in one place! 🎩✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'hash to slot_wrapper' is partially related to the changeset. It refers to a real aspect of the change—the implementation of hash using slot wrappers—but it's not the primary focus. The main change is the introduction of SlotFunc to type-erase and uniformly dispatch slot functions (Init and Hash variants), which is broader than just hash conversion.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
  • X
  • Mastodon
  • Reddit
  • LinkedIn

Comment @coderabbitai help to get the list of available commands and usage tips.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@youknowone
__hash__ to slot_wrapper
2515109
@youknowone
youknowone force-pushed the slot-hash branch from 7c2a0d9 to 2515109 Compare December 24, 2025 08:52
@youknowone
youknowone marked this pull request as ready for review December 24, 2025 09:51
ShaharNaveh
ShaharNaveh reviewed Dec 24, 2025
View reviewed changes
Comment thread crates/vm/src/builtins/descriptor.rs
SlotFunc::Hash(func) => {
if !args.args.is_empty() || !args.kwargs.is_empty() {
return Err(
vm.new_type_error("__hash__() takes no arguments (1 given)".to_owned())

@ShaharNaveh ShaharNaveh Dec 24, 2025

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Suggested change
vm.new_type_error("__hash__() takes no arguments (1 given)".to_owned())
vm.new_type_error("__hash__() takes no arguments (1 given)")

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
ShaharNaveh
ShaharNaveh approved these changes Dec 24, 2025
View reviewed changes

@ShaharNaveh ShaharNaveh left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

lgtm

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
coderabbitai[bot]
coderabbitai Bot reviewed Dec 24, 2025
View reviewed changes

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

There was a problem hiding this comment.

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
crates/vm/src/class.rs (1)

156-171: Function pointer comparison may be unreliable; consider alternative approaches.

The comparison hash_func as usize != hash_not_implemented as usize on line 159 casts function pointers to usize for equality checking. While this may work in practice, comparing function pointers via cast to integers is not guaranteed to be reliable across all platforms and optimization levels.

Consider these alternatives:

  1. Use std::ptr::eq for function pointer comparison
  2. Add a marker trait or use a different mechanism to identify special sentinel functions
🔎 Proposed fix using std::ptr::eq
-        if let Some(hash_func) = class.slots.hash.load()
-            && hash_func as usize != hash_not_implemented as usize
-        {
+        if let Some(hash_func) = class.slots.hash.load() {
+            let is_not_implemented = std::ptr::eq(
+                hash_func as *const (),
+                hash_not_implemented as *const ()
+            );
+            if !is_not_implemented {
             let hash_name = identifier!(ctx, __hash__);
             if !class.attributes.read().contains_key(hash_name) {
                 let wrapper = PySlotWrapper {
                     typ: class,
                     name: ctx.intern_str("__hash__"),
                     wrapped: SlotFunc::Hash(hash_func),
                     doc: Some("Return hash(self)."),
                 };
                 class.set_attr(hash_name, wrapper.into_ref(ctx).into());
             }
+            }
         }
crates/vm/src/builtins/descriptor.rs (1)

420-428: Clarify the error message for hash argument count.

The error message on line 423 says "__hash__() takes no arguments (1 given)", but this is potentially confusing since the self argument has already been consumed at this point. The message should reflect the actual situation more accurately.

🔎 Proposed improvement
                 if !args.args.is_empty() || !args.kwargs.is_empty() {
                     return Err(
-                        vm.new_type_error("__hash__() takes no arguments (1 given)".to_owned())
+                        vm.new_type_error(format!(
+                            "__hash__() takes exactly one argument ({} given)",
+                            args.args.len() + 1
+                        ))
                     );
                 }

Or simply:

-                        vm.new_type_error("__hash__() takes no arguments (1 given)".to_owned())
+                        vm.new_type_error("__hash__() takes exactly 1 argument (self)".to_owned())
📜 Review details

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3d7e521 and 2515109.

📒 Files selected for processing (3)
  • crates/vm/src/builtins/descriptor.rs
  • crates/vm/src/class.rs
  • crates/vm/src/types/slot.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.rs: Follow the default rustfmt code style by running cargo fmt to format Rust code
Always run clippy to lint Rust code (cargo clippy) before completing tasks and fix any warnings or lints introduced by changes
Follow Rust best practices for error handling and memory management
Use the macro system (pyclass, pymodule, pyfunction, etc.) when implementing Python functionality in Rust

Files:

  • crates/vm/src/types/slot.rs
  • crates/vm/src/class.rs
  • crates/vm/src/builtins/descriptor.rs
🧠 Learnings (1)
📚 Learning: 2025-11-29T12:17:28.606Z
Learnt from: CR
Repo: RustPython/RustPython PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T12:17:28.606Z
Learning: Applies to **/*.rs : Use the macro system (`pyclass`, `pymodule`, `pyfunction`, etc.) when implementing Python functionality in Rust

Applied to files:

  • crates/vm/src/builtins/descriptor.rs
🧬 Code graph analysis (1)
crates/vm/src/class.rs (1)
crates/vm/src/types/slot.rs (1)
  • hash_not_implemented (374-376)
🔇 Additional comments (8)
crates/vm/src/class.rs (3)

5-8: LGTM!

The import changes properly bring in SlotFunc from the descriptor module and maintain logical grouping.


146-154: LGTM!

The __init__ wrapper correctly uses the new SlotFunc::Init variant to wrap the init function, maintaining the existing functionality while adopting the unified slot function abstraction.


158-171: The hash wrapper implementation is correct and properly handles all cases.

The code correctly:

  1. Creates wrappers for all types with non-null hash slots (excluding hash_not_implemented)
  2. Prevents duplicates via the contains_key check before insertion
  3. Integrates properly with the slot dispatch mechanism through SlotFunc::Hash
  4. Has appropriate special handling for unhashable types (sets __hash__ to None when hash_not_implemented is the slot function)

The implementation aligns with the expected behavior for exposing slot-based hash functions to Python as __hash__ methods.

crates/vm/src/builtins/descriptor.rs (4)

9-10: LGTM!

The import of HashFunc is properly added to support the new SlotFunc::Hash variant.


395-411: LGTM! Well-designed type-erased slot function abstraction.

The SlotFunc enum effectively type-erases different slot function signatures, mirroring CPython's void* d_wrapped approach. The Clone and Copy derives are appropriate for function pointers, and the Debug implementation is helpful without exposing internal details.


468-486: LGTM! Proper integration with SlotFunc.

The PySlotWrapper::call implementation correctly:

  1. Extracts the first argument as self
  2. Validates the type of self against the expected type
  3. Delegates to SlotFunc::call with the remaining arguments

The unified dispatch mechanism is well-implemented.


543-549: LGTM! Bound method-wrapper correctly uses SlotFunc.

The PyMethodWrapper::call implementation properly delegates to SlotFunc::call with the bound object and arguments, maintaining consistency with the slot wrapper mechanism.

crates/vm/src/types/slot.rs (1)

1101-1101: No issues found. All 27+ implementations of the Hashable trait properly define the required fn hash(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyHash> method, with zero remaining references to any removed __hash__ method. The SlotFunc::Hash wrapper is correctly integrated in the class system.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
@youknowone
youknowone merged commit c4e7728 into RustPython:main Dec 24, 2025
13 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@youknowone
youknowone deleted the slot-hash branch December 24, 2025 09:56
This was referenced Dec 24, 2025
iter with slot-wrapper #6488
Merged
Add tp_str #6495
Merged
PyWrapperDescrObject and rewrite toggle_slot #6536
Merged
Panic in hash wrapping when user hash returns oversized int #6550
Closed
Handle oversized __hash__ results without panicking #6561
Merged
@coderabbitai coderabbitai Bot mentioned this pull request Jan 1, 2026
sequence, mapping slots and fix separate __delitem__ slots #6621
Merged
@coderabbitai coderabbitai Bot mentioned this pull request Jan 22, 2026
fix clippy 1.93.0 #6836
Merged
@coderabbitai coderabbitai Bot mentioned this pull request Mar 15, 2026
Implement missing slots for NoneType #7437
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@coderabbitai coderabbitai[bot] coderabbitai[bot] left review comments
@ShaharNaveh ShaharNaveh ShaharNaveh approved these changes

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@youknowone @ShaharNaveh
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.