Skip to content

Commit aa0353a

Browse files
authored
Fix best_base to select proper base class (RustPython#5324)
* add __basicsize__ getter * modify best_base function to get proper base * inherit basicsize from the base type --------- Signed-off-by: snowapril <sinjihng@gmail.com>
1 parent 63c3f31 commit aa0353a

File tree

4 files changed

+48
-43
lines changed

4 files changed

+48
-43
lines changed

Lib/test/test_builtin.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2368,8 +2368,6 @@ def __del__(self):
23682368

23692369

23702370
class TestType(unittest.TestCase):
2371-
# TODO: RUSTPYTHON
2372-
@unittest.expectedFailure
23732371
def test_new_type(self):
23742372
A = type('A', (), {})
23752373
self.assertEqual(A.__name__, 'A')
@@ -2472,8 +2470,6 @@ def test_type_doc(self):
24722470
A.__doc__ = doc
24732471
self.assertEqual(A.__doc__, doc)
24742472

2475-
# TODO: RUSTPYTHON
2476-
@unittest.expectedFailure
24772473
def test_bad_args(self):
24782474
with self.assertRaises(TypeError):
24792475
type()

Lib/test/test_descr.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -823,8 +823,6 @@ class X(C, int()):
823823
class X(int(), C):
824824
pass
825825

826-
# TODO: RUSTPYTHON
827-
@unittest.expectedFailure
828826
def test_module_subclasses(self):
829827
# Testing Python subclass of module...
830828
log = []
@@ -1500,8 +1498,6 @@ class someclass(metaclass=dynamicmetaclass):
15001498
pass
15011499
self.assertNotEqual(someclass, object)
15021500

1503-
# TODO: RUSTPYTHON
1504-
@unittest.expectedFailure
15051501
def test_errors(self):
15061502
# Testing errors...
15071503
try:

Lib/test/test_posix.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,8 +1680,6 @@ def test_initgroups(self):
16801680
posix.initgroups(name, g)
16811681
self.assertIn(g, posix.getgroups())
16821682

1683-
# TODO: RUSTPYTHON: TypeError: Unexpected keyword argument setpgroup
1684-
@unittest.expectedFailure
16851683
@unittest.skipUnless(hasattr(posix, 'setgroups'),
16861684
"test needs posix.setgroups()")
16871685
def test_setgroups(self):

vm/src/builtins/type.rs

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ impl PyType {
205205
if base.slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
206206
slots.flags |= PyTypeFlags::HAS_DICT
207207
}
208+
if slots.basicsize == 0 {
209+
slots.basicsize = base.slots.basicsize;
210+
}
208211

209212
if let Some(qualname) = attrs.get(identifier!(ctx, __qualname__)) {
210213
if !qualname.fast_isinstance(ctx.types.str_type) {
@@ -253,6 +256,9 @@ impl PyType {
253256
if base.slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
254257
slots.flags |= PyTypeFlags::HAS_DICT
255258
}
259+
if slots.basicsize == 0 {
260+
slots.basicsize = base.slots.basicsize;
261+
}
256262

257263
let bases = vec![base.clone()];
258264
let mro = base.iter_mro().map(|x| x.to_owned()).collect();
@@ -470,6 +476,11 @@ impl PyType {
470476
self.slots.flags.bits()
471477
}
472478

479+
#[pygetset(magic)]
480+
fn basicsize(&self) -> usize {
481+
self.slots.basicsize
482+
}
483+
473484
#[pygetset]
474485
pub fn __name__(&self, vm: &VirtualMachine) -> PyStrRef {
475486
self.name_inner(
@@ -1313,22 +1324,29 @@ fn calculate_meta_class(
13131324
Ok(winner)
13141325
}
13151326

1327+
fn solid_base(typ: &PyTypeRef, vm: &VirtualMachine) -> PyTypeRef {
1328+
let base = if let Some(base) = &typ.base {
1329+
solid_base(base, vm)
1330+
} else {
1331+
vm.ctx.types.object_type.to_owned()
1332+
};
1333+
1334+
// TODO: itemsize comparation also needed
1335+
if typ.basicsize() != base.basicsize() {
1336+
typ.clone()
1337+
} else {
1338+
base
1339+
}
1340+
}
1341+
13161342
fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult<PyTypeRef> {
1317-
// let mut base = None;
1318-
// let mut winner = None;
1343+
let mut base: Option<PyTypeRef> = None;
1344+
let mut winner: Option<PyTypeRef> = None;
13191345

13201346
for base_i in bases {
1321-
// base_proto = PyTuple_GET_ITEM(bases, i);
1322-
// if (!PyType_Check(base_proto)) {
1323-
// PyErr_SetString(
1324-
// PyExc_TypeError,
1325-
// "bases must be types");
1326-
// return NULL;
1327-
// }
1328-
// base_i = (PyTypeObject *)base_proto;
1329-
// if (base_i->slot_dict == NULL) {
1330-
// if (PyType_Ready(base_i) < 0)
1331-
// return NULL;
1347+
// if !base_i.fast_issubclass(vm.ctx.types.type_type) {
1348+
// println!("base_i type : {}", base_i.name());
1349+
// return Err(vm.new_type_error("best must be types".into()));
13321350
// }
13331351

13341352
if !base_i.slots.flags.has_feature(PyTypeFlags::BASETYPE) {
@@ -1337,28 +1355,25 @@ fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult<PyTypeRef> {
13371355
base_i.name()
13381356
)));
13391357
}
1340-
// candidate = solid_base(base_i);
1341-
// if (winner == NULL) {
1342-
// winner = candidate;
1343-
// base = base_i;
1344-
// }
1345-
// else if (PyType_IsSubtype(winner, candidate))
1346-
// ;
1347-
// else if (PyType_IsSubtype(candidate, winner)) {
1348-
// winner = candidate;
1349-
// base = base_i;
1350-
// }
1351-
// else {
1352-
// PyErr_SetString(
1353-
// PyExc_TypeError,
1354-
// "multiple bases have "
1355-
// "instance lay-out conflict");
1356-
// return NULL;
1357-
// }
1358+
1359+
let candidate = solid_base(base_i, vm);
1360+
if winner.is_none() {
1361+
winner = Some(candidate.clone());
1362+
base = Some(base_i.clone());
1363+
} else if winner.as_ref().unwrap().fast_issubclass(&candidate) {
1364+
// Do nothing
1365+
} else if candidate.fast_issubclass(winner.as_ref().unwrap()) {
1366+
winner = Some(candidate.clone());
1367+
base = Some(base_i.clone());
1368+
} else {
1369+
return Err(
1370+
vm.new_type_error("multiple bases have instance layout conflict".to_string())
1371+
);
1372+
}
13581373
}
13591374

1360-
// FIXME: Ok(base.unwrap()) is expected
1361-
Ok(bases[0].clone())
1375+
debug_assert!(base.is_some());
1376+
Ok(base.unwrap())
13621377
}
13631378

13641379
#[cfg(test)]

0 commit comments

Comments
 (0)