Skip to content

Fix isinstance #5869

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 30, 2025
Merged

Fix isinstance #5869

merged 3 commits into from
Jun 30, 2025

Conversation

youknowone
Copy link
Member

@youknowone youknowone commented Jun 30, 2025

Summary by CodeRabbit

  • New Features
    • Introduced a new method for special method lookup that mimics CPython's behavior, allowing attribute retrieval in the type's method resolution order without raising exceptions.
  • Refactor
    • Improved the logic and safety of subclass and instance checks, making the behavior more consistent with CPython and removing unsafe code patterns.

Copy link

coderabbitai bot commented Jun 30, 2025

Walkthrough

Two new methods were introduced in the type system to provide low-level, exception-free attribute lookups directly in the MRO, closely matching CPython's behavior. Object protocol logic was refactored for safety and clarity, and a new method for special method lookup was added, ensuring correct handling of descriptors and error masking as in CPython.

Changes

File(s) Change Summary
vm/src/builtins/type.rs Added find_name_in_mro (private) and lookup_ref (public) methods to PyType for direct, exception-free attribute lookup in the MRO.
vm/src/protocol/object.rs Refactored abstract_issubclass for safer, clearer control flow; updated special method lookups to use new lookup_special method; added lookup_special to PyObject for CPython-like behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant PyType
    participant PyStrInterned
    participant MRO

    Caller->>PyType: lookup_ref(name: &PyStr, vm)
    PyType->>PyStrInterned: Intern name
    PyType->>MRO: find_name_in_mro(interned_name)
    MRO-->>PyType: Return attribute value or None
    PyType-->>Caller: Return Option<PyObjectRef>
Loading
sequenceDiagram
    participant Caller
    participant PyObject
    participant PyType
    participant MRO
    participant Descriptor

    Caller->>PyObject: lookup_special(attr: &PyStr, vm)
    PyObject->>PyType: Get type and MRO
    PyType->>MRO: Search for attr in MRO dicts
    MRO-->>PyType: Return value or None
    alt Found and is descriptor
        PyType->>Descriptor: Call __get__(self, instance, owner)
        Descriptor-->>PyType: Return result or None on exception
    end
    PyType-->>PyObject: Return Option<PyObjectRef>
    PyObject-->>Caller: Return Option<PyObjectRef>
Loading

Poem

In the warren of types, a lookup anew,
With MRO magic, the attributes flew.
No exceptions to catch, just a None if you must,
And special methods found with descriptor trust.
With safety and clarity, the code now aligns—
A hop and a skip through Pythonic designs! 🐇


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6ff541 and 899abbb.

📒 Files selected for processing (2)
  • vm/src/builtins/type.rs (1 hunks)
  • vm/src/protocol/object.rs (6 hunks)
🧰 Additional context used
🧠 Learnings (1)
vm/src/builtins/type.rs (3)
Learnt from: CR
PR: RustPython/RustPython#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-06-26T12:52:11.138Z
Learning: When implementing a Python module in Rust for RustPython, use the #[pymodule] attribute and expose functions and classes using #[pyfunction], #[pyclass], and #[pymethod] as appropriate.
Learnt from: CR
PR: RustPython/RustPython#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-06-26T12:52:11.138Z
Learning: To find unimplemented methods and contribution opportunities, run './whats_left.py' in the RustPython repository.
Learnt from: CR
PR: RustPython/RustPython#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-06-26T12:52:11.138Z
Learning: Use the macro system (such as 'pyclass', 'pymodule', 'pyfunction') when implementing Python functionality in Rust for RustPython.
🔇 Additional comments (6)
vm/src/builtins/type.rs (2)

386-402: LGTM! Correct implementation of CPython's find_name_in_mro.

The method correctly implements direct dictionary lookup in the MRO, bypassing descriptors and other attribute access machinery as intended. The logic matches CPython's behavior by first checking the type's own attributes before traversing the MRO.


404-413: Correct implementation of _PyType_LookupRef with proper error handling.

The method properly handles the case where the string might not be interned (returning None), which matches CPython's behavior. The use of find_name_in_mro ensures descriptor logic is bypassed as expected.

vm/src/protocol/object.rs (4)

412-442: Excellent refactoring for safety and clarity!

The removal of unsafe pointer casts and the clearer control flow significantly improves code maintainability. The single inheritance optimization in the loop is a nice touch that avoids unnecessary recursion while maintaining the same behavior.


527-531: Correct alignment with CPython's special method lookup behavior.

Using lookup_special instead of vm.get_special_method properly implements CPython's semantics where special methods are looked up in the type's MRO without checking the instance dictionary. The change from invoke to call is also appropriate.

Also applies to: 618-622


541-552: Consistent use of is_subtype for type checking.

The change from fast_isinstance/fast_issubclass to is_subtype provides more direct and consistent subtype checking throughout the codebase.

Also applies to: 570-570


749-767: Well-implemented special method lookup matching CPython's semantics.

The lookup_special method correctly implements CPython's _PyObject_LookupSpecial:

  • Uses the new lookup_ref for MRO lookup without instance dict
  • Properly handles descriptors by calling __get__
  • Correctly masks exceptions by returning None

This is crucial for proper special method resolution in isinstance/issubclass checks.

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@youknowone youknowone force-pushed the issubclass branch 2 times, most recently from 76c7882 to b295e4f Compare June 30, 2025 00:35
@youknowone youknowone marked this pull request as ready for review June 30, 2025 01:18
@youknowone youknowone merged commit 66a1138 into RustPython:main Jun 30, 2025
12 checks passed
@youknowone youknowone deleted the issubclass branch June 30, 2025 01:35
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.

1 participant