Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix multiple inheritance
  • Loading branch information
youknowone committed Aug 26, 2025
commit be54bc0dfd80788e5a63ce5f39ca4f4fa9c156c0
2 changes: 0 additions & 2 deletions Lib/test/test_patma.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ def check_mapping_then_sequence(x):
case [*_]:
return "seq"

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_multiple_inheritance_mapping(self):
class C:
pass
Expand All @@ -63,7 +62,6 @@ class M4(dict, collections.abc.Sequence, C):
self.assertEqual(self.check_mapping_then_sequence(M3()), "map")
self.assertEqual(self.check_mapping_then_sequence(M4()), "map")

@unittest.expectedFailure # TODO: RUSTPYTHON
def test_multiple_inheritance_sequence(self):
class C:
pass
Expand Down
27 changes: 20 additions & 7 deletions vm/src/builtins/type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,25 @@ impl PyType {
linearise_mro(mros)
}

/// Inherit SEQUENCE and MAPPING flags from base class (CPython: inherit_patma_flags)
fn inherit_patma_flags(slots: &mut PyTypeSlots, base: &PyRef<Self>) {
/// Inherit SEQUENCE and MAPPING flags from base classes
/// Check all bases in order and inherit the first SEQUENCE or MAPPING flag found
fn inherit_patma_flags(slots: &mut PyTypeSlots, bases: &[PyRef<Self>]) {
const COLLECTION_FLAGS: PyTypeFlags = PyTypeFlags::from_bits_truncate(
PyTypeFlags::SEQUENCE.bits() | PyTypeFlags::MAPPING.bits(),
);
if !slots.flags.intersects(COLLECTION_FLAGS) {
slots.flags |= base.slots.flags & COLLECTION_FLAGS;

// If flags are already set, don't override
if slots.flags.intersects(COLLECTION_FLAGS) {
return;
}

// Check each base in order and inherit the first collection flag found
for base in bases {
let base_flags = base.slots.flags & COLLECTION_FLAGS;
if !base_flags.is_empty() {
slots.flags |= base_flags;
return;
}
}
}

Expand Down Expand Up @@ -300,8 +312,8 @@ impl PyType {
slots.flags |= PyTypeFlags::HAS_DICT
}

// Inherit SEQUENCE and MAPPING flags from base class
Self::inherit_patma_flags(&mut slots, &base);
// Inherit SEQUENCE and MAPPING flags from base classes
Self::inherit_patma_flags(&mut slots, &bases);

// Check for __abc_tpflags__ from ABCMeta (for collections.abc.Sequence, Mapping, etc.)
Self::check_abc_tpflags(&mut slots, &attrs, &bases, ctx);
Expand Down Expand Up @@ -359,7 +371,8 @@ impl PyType {
}

// Inherit SEQUENCE and MAPPING flags from base class
Self::inherit_patma_flags(&mut slots, &base);
// For static types, we only have a single base
Self::inherit_patma_flags(&mut slots, std::slice::from_ref(&base));

if slots.basicsize == 0 {
slots.basicsize = base.slots.basicsize;
Expand Down