From ac107988c0ab68d0cf610929a8c77fd11d49d174 Mon Sep 17 00:00:00 2001 From: snowapril Date: Sun, 12 May 2024 22:09:31 +0900 Subject: [PATCH 1/7] add __basicsize__ getter --- vm/src/builtins/type.rs | 56 ++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index e6f81d24b2..ad60da18cc 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -470,6 +470,11 @@ impl PyType { self.slots.flags.bits() } + #[pygetset(magic)] + fn basicsize(&self) -> usize { + self.slots.basicsize + } + #[pygetset] pub fn __name__(&self, vm: &VirtualMachine) -> PyStrRef { self.name_inner( @@ -1313,22 +1318,23 @@ fn calculate_meta_class( Ok(winner) } +fn solid_base(typ: &PyTypeRef, vm: &VirtualMachine) -> Option { + let result = if let Some(base) = &typ.base { + solid_base(&base, vm) + } else { + Some(vm.ctx.types.object_type.to_owned()) + }; + + result +} + fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult { - // let mut base = None; - // let mut winner = None; + let mut base: Option = None; + let mut winner: Option = None; for base_i in bases { - // base_proto = PyTuple_GET_ITEM(bases, i); - // if (!PyType_Check(base_proto)) { - // PyErr_SetString( - // PyExc_TypeError, - // "bases must be types"); - // return NULL; - // } - // base_i = (PyTypeObject *)base_proto; - // if (base_i->slot_dict == NULL) { - // if (PyType_Ready(base_i) < 0) - // return NULL; + // if !base_i.fast_issubclass(vm.ctx.types.type_type) { + // return Err(vm.new_type_error("best must be types".into())); // } if !base_i.slots.flags.has_feature(PyTypeFlags::BASETYPE) { @@ -1337,27 +1343,13 @@ fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult { base_i.name() ))); } - // candidate = solid_base(base_i); - // if (winner == NULL) { - // winner = candidate; - // base = base_i; - // } - // else if (PyType_IsSubtype(winner, candidate)) - // ; - // else if (PyType_IsSubtype(candidate, winner)) { - // winner = candidate; - // base = base_i; - // } - // else { - // PyErr_SetString( - // PyExc_TypeError, - // "multiple bases have " - // "instance lay-out conflict"); - // return NULL; - // } + + let candidate = solid_base(&base_i, vm); + println!("candidate type : {}", candidate.unwrap().name()); } - // FIXME: Ok(base.unwrap()) is expected + // Ok(base.unwrap()) + Ok(bases[0].clone()) } From 792ba4707c8a8fd8262dd8375c721fbedf899a05 Mon Sep 17 00:00:00 2001 From: snowapril Date: Sun, 12 May 2024 22:09:46 +0900 Subject: [PATCH 2/7] modify best_base function to get proper base --- vm/src/builtins/type.rs | 74 ++++++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 12 deletions(-) diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index ad60da18cc..9a01cf301d 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -1320,21 +1320,34 @@ fn calculate_meta_class( fn solid_base(typ: &PyTypeRef, vm: &VirtualMachine) -> Option { let result = if let Some(base) = &typ.base { - solid_base(&base, vm) + solid_base(&base, vm).unwrap() } else { - Some(vm.ctx.types.object_type.to_owned()) + vm.ctx.types.object_type.to_owned() }; - result + if result.slots.basicsize != typ.slots.basicsize { + Some(typ) + } else { + Some(result) + } } fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult { - let mut base: Option = None; - let mut winner: Option = None; + // let mut base = None; + // let mut winner = None; for base_i in bases { - // if !base_i.fast_issubclass(vm.ctx.types.type_type) { - // return Err(vm.new_type_error("best must be types".into())); + // base_proto = PyTuple_GET_ITEM(bases, i); + // if (!PyType_Check(base_proto)) { + // PyErr_SetString( + // PyExc_TypeError, + // "bases must be types"); + // return NULL; + // } + // base_i = (PyTypeObject *)base_proto; + // if (base_i->slot_dict == NULL) { + // if (PyType_Ready(base_i) < 0) + // return NULL; // } if !base_i.slots.flags.has_feature(PyTypeFlags::BASETYPE) { @@ -1343,14 +1356,51 @@ fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult { base_i.name() ))); } - - let candidate = solid_base(&base_i, vm); - println!("candidate type : {}", candidate.unwrap().name()); + // candidate = solid_base(base_i); + // if (winner == NULL) { + // winner = candidate; + // base = base_i; + // } + // else if (PyType_IsSubtype(winner, candidate)) + // ; + // else if (PyType_IsSubtype(candidate, winner)) { + // winner = candidate; + // base = base_i; + // } + // else { + // PyErr_SetString( + // PyExc_TypeError, + // "multiple bases have " + // "instance lay-out conflict"); + // return NULL; + // } } - // Ok(base.unwrap()) - + // FIXME: Ok(base.unwrap()) is expected Ok(bases[0].clone()) + + // let mut base: Option = None; + // let mut winner: Option = None; + + // for base_i in bases { + // // if !base_i.fast_issubclass(vm.ctx.types.type_type) { + // // return Err(vm.new_type_error("best must be types".into())); + // // } + + // if !base_i.slots.flags.has_feature(PyTypeFlags::BASETYPE) { + // return Err(vm.new_type_error(format!( + // "type '{}' is not an acceptable base type", + // base_i.name() + // ))); + // } + + // let candidate = solid_base(&base_i, vm); + // println!("candidate type : {}", candidate.unwrap().name()); + // } + + // // Ok(base.unwrap()) + + // Ok(bases[0].clone()) } #[cfg(test)] From a6accc1f219b95d1e7649ffc9d181207e67e6205 Mon Sep 17 00:00:00 2001 From: snowapril Date: Wed, 15 May 2024 22:01:08 +0900 Subject: [PATCH 3/7] modify best_base to select proper base --- vm/src/builtins/type.rs | 93 ++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 62 deletions(-) diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index 9a01cf301d..a67c0453a5 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -1318,36 +1318,31 @@ fn calculate_meta_class( Ok(winner) } -fn solid_base(typ: &PyTypeRef, vm: &VirtualMachine) -> Option { - let result = if let Some(base) = &typ.base { - solid_base(&base, vm).unwrap() + +fn solid_base(typ: &PyTypeRef, vm: &VirtualMachine) -> PyTypeRef { + let base = if let Some(base) = &typ.base { + solid_base(&base, vm) } else { vm.ctx.types.object_type.to_owned() }; - if result.slots.basicsize != typ.slots.basicsize { - Some(typ) + // TODO: itemsize comparation also needed + if typ.basicsize() != base.basicsize() { + typ.clone() } else { - Some(result) + base } } fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult { - // let mut base = None; - // let mut winner = None; + + let mut base: Option = None; + let mut winner: Option = None; for base_i in bases { - // base_proto = PyTuple_GET_ITEM(bases, i); - // if (!PyType_Check(base_proto)) { - // PyErr_SetString( - // PyExc_TypeError, - // "bases must be types"); - // return NULL; - // } - // base_i = (PyTypeObject *)base_proto; - // if (base_i->slot_dict == NULL) { - // if (PyType_Ready(base_i) < 0) - // return NULL; + // if !base_i.fast_issubclass(vm.ctx.types.type_type) { + // println!("base_i type : {}", base_i.name()); + // return Err(vm.new_type_error("best must be types".into())); // } if !base_i.slots.flags.has_feature(PyTypeFlags::BASETYPE) { @@ -1356,51 +1351,25 @@ fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult { base_i.name() ))); } - // candidate = solid_base(base_i); - // if (winner == NULL) { - // winner = candidate; - // base = base_i; - // } - // else if (PyType_IsSubtype(winner, candidate)) - // ; - // else if (PyType_IsSubtype(candidate, winner)) { - // winner = candidate; - // base = base_i; - // } - // else { - // PyErr_SetString( - // PyExc_TypeError, - // "multiple bases have " - // "instance lay-out conflict"); - // return NULL; - // } - } - - // FIXME: Ok(base.unwrap()) is expected - Ok(bases[0].clone()) - // let mut base: Option = None; - // let mut winner: Option = None; - - // for base_i in bases { - // // if !base_i.fast_issubclass(vm.ctx.types.type_type) { - // // return Err(vm.new_type_error("best must be types".into())); - // // } - - // if !base_i.slots.flags.has_feature(PyTypeFlags::BASETYPE) { - // return Err(vm.new_type_error(format!( - // "type '{}' is not an acceptable base type", - // base_i.name() - // ))); - // } - - // let candidate = solid_base(&base_i, vm); - // println!("candidate type : {}", candidate.unwrap().name()); - // } - - // // Ok(base.unwrap()) + let candidate = solid_base(&base_i, vm); + if winner.is_none() { + winner = Some(candidate.clone()); + base = Some(base_i.clone()); + } else if winner.as_ref().unwrap().fast_issubclass(&candidate) { + // Do nothing + } else if candidate.fast_issubclass(winner.as_ref().unwrap()) { + winner = Some(candidate.clone()); + base = Some(base_i.clone()); + } else { + return Err(vm.new_type_error( + "multiple bases have instance layout conflict".to_string(), + )); + } + } - // Ok(bases[0].clone()) + debug_assert!(base.is_some()); + Ok(base.unwrap()) } #[cfg(test)] From ffa8950a0656bcdf5a4d0ec940b81c2c31ef4c64 Mon Sep 17 00:00:00 2001 From: snowapril Date: Sun, 19 May 2024 15:16:15 +0900 Subject: [PATCH 4/7] remove expected failures Signed-off-by: snowapril --- Lib/test/test_builtin.py | 4 ---- Lib/test/test_descr.py | 4 ---- Lib/test/test_posix.py | 2 -- 3 files changed, 10 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 1f28cd7e8a..13d67e1855 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -2368,8 +2368,6 @@ def __del__(self): class TestType(unittest.TestCase): - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_new_type(self): A = type('A', (), {}) self.assertEqual(A.__name__, 'A') @@ -2472,8 +2470,6 @@ def test_type_doc(self): A.__doc__ = doc self.assertEqual(A.__doc__, doc) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_bad_args(self): with self.assertRaises(TypeError): type() diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 98fd839950..4d651a2dde 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -823,8 +823,6 @@ class X(C, int()): class X(int(), C): pass - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_module_subclasses(self): # Testing Python subclass of module... log = [] @@ -1500,8 +1498,6 @@ class someclass(metaclass=dynamicmetaclass): pass self.assertNotEqual(someclass, object) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_errors(self): # Testing errors... try: diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py index cec1cb6ce4..7e9e261d78 100644 --- a/Lib/test/test_posix.py +++ b/Lib/test/test_posix.py @@ -1680,8 +1680,6 @@ def test_initgroups(self): posix.initgroups(name, g) self.assertIn(g, posix.getgroups()) - # TODO: RUSTPYTHON: TypeError: Unexpected keyword argument setpgroup - @unittest.expectedFailure @unittest.skipUnless(hasattr(posix, 'setgroups'), "test needs posix.setgroups()") def test_setgroups(self): From c1fe1f9fdb1fa958f0eda5508ec3e6ddf0bc3df0 Mon Sep 17 00:00:00 2001 From: snowapril Date: Sat, 18 May 2024 15:46:49 +0900 Subject: [PATCH 5/7] fix clippy warning --- vm/src/builtins/type.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index a67c0453a5..44dba0ac5b 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -1321,7 +1321,7 @@ fn calculate_meta_class( fn solid_base(typ: &PyTypeRef, vm: &VirtualMachine) -> PyTypeRef { let base = if let Some(base) = &typ.base { - solid_base(&base, vm) + solid_base(base, vm) } else { vm.ctx.types.object_type.to_owned() }; @@ -1352,7 +1352,7 @@ fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult { ))); } - let candidate = solid_base(&base_i, vm); + let candidate = solid_base(base_i, vm); if winner.is_none() { winner = Some(candidate.clone()); base = Some(base_i.clone()); From abf8b13d3e8bcdd251fa316a37bac820e4673c79 Mon Sep 17 00:00:00 2001 From: snowapril Date: Sat, 18 May 2024 17:42:44 +0900 Subject: [PATCH 6/7] inherit basicsize from the base type --- vm/src/builtins/type.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index 44dba0ac5b..743218ae23 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -205,6 +205,9 @@ impl PyType { if base.slots.flags.has_feature(PyTypeFlags::HAS_DICT) { slots.flags |= PyTypeFlags::HAS_DICT } + if slots.basicsize == 0 { + slots.basicsize = base.slots.basicsize; + } if let Some(qualname) = attrs.get(identifier!(ctx, __qualname__)) { if !qualname.fast_isinstance(ctx.types.str_type) { @@ -253,6 +256,9 @@ impl PyType { if base.slots.flags.has_feature(PyTypeFlags::HAS_DICT) { slots.flags |= PyTypeFlags::HAS_DICT } + if slots.basicsize == 0 { + slots.basicsize = base.slots.basicsize; + } let bases = vec![base.clone()]; let mro = base.iter_mro().map(|x| x.to_owned()).collect(); From d679165cd7cab7558196c54cea55ee1c7f555de9 Mon Sep 17 00:00:00 2001 From: snowapril Date: Sat, 18 May 2024 17:59:27 +0900 Subject: [PATCH 7/7] run cargo fmt --- vm/src/builtins/type.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/vm/src/builtins/type.rs b/vm/src/builtins/type.rs index 743218ae23..0e80021d99 100644 --- a/vm/src/builtins/type.rs +++ b/vm/src/builtins/type.rs @@ -1324,7 +1324,6 @@ fn calculate_meta_class( Ok(winner) } - fn solid_base(typ: &PyTypeRef, vm: &VirtualMachine) -> PyTypeRef { let base = if let Some(base) = &typ.base { solid_base(base, vm) @@ -1341,7 +1340,6 @@ fn solid_base(typ: &PyTypeRef, vm: &VirtualMachine) -> PyTypeRef { } fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult { - let mut base: Option = None; let mut winner: Option = None; @@ -1368,9 +1366,9 @@ fn best_base(bases: &[PyTypeRef], vm: &VirtualMachine) -> PyResult { winner = Some(candidate.clone()); base = Some(base_i.clone()); } else { - return Err(vm.new_type_error( - "multiple bases have instance layout conflict".to_string(), - )); + return Err( + vm.new_type_error("multiple bases have instance layout conflict".to_string()) + ); } }