diff --git a/Lib/test/test_set.py b/Lib/test/test_set.py index a0b50df8f..4d062b42d 100644 --- a/Lib/test/test_set.py +++ b/Lib/test/test_set.py @@ -828,7 +828,6 @@ class TestFrozenSetSubclass(TestFrozenSet): thetype = FrozenSetSubclass basetype = frozenset - @unittest.expectedFailure # TODO: RUSTPYTHON def test_keywords_in_subclass(self): class subclass(frozenset): pass diff --git a/crates/vm/src/builtins/set.rs b/crates/vm/src/builtins/set.rs index a8f3e83c8..1481bc1b3 100644 --- a/crates/vm/src/builtins/set.rs +++ b/crates/vm/src/builtins/set.rs @@ -958,31 +958,54 @@ impl Constructor for PyFrozenSet { type Args = Vec; fn slot_new(cls: PyTypeRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult { - let iterable: OptionalArg = args.bind(vm)?; + let is_exact_frozenset = cls.is(vm.ctx.types.frozenset_type); + let is_frozenset_init = { + let cls_init = cls.slots.init.load().map(|init| init as usize); + let frozenset_init = vm + .ctx + .types + .frozenset_type + .slots + .init + .load() + .map(|init| init as usize); + cls_init == frozenset_init + }; // Optimizations for exact frozenset type - if cls.is(vm.ctx.types.frozenset_type) { + let iterable_opt = if is_exact_frozenset || is_frozenset_init { + let iterable: OptionalArg = args.bind(vm)?; + // Return exact frozenset as-is - if let OptionalArg::Present(ref input) = iterable - && let Ok(fs) = input.clone().downcast_exact::(vm) + if is_exact_frozenset + && let OptionalArg::Present(input) = &iterable + && input.class().is(vm.ctx.types.frozenset_type) { - return Ok(fs.into_pyref().into()); + return Ok(input.clone()); } - // Return empty frozenset singleton - if iterable.is_missing() { - return Ok(vm.ctx.empty_frozenset.clone().into()); + iterable.into_option() + } else { + match &args.args[..] { + [] => None, + [iterable] => Some(iterable.clone()), + slice => { + return Err(vm.new_type_error(format!( + "frozenset expected at most 1 argument, got {}", + slice.len() + ))); + } } - } + }; - let elements: Vec = if let OptionalArg::Present(iterable) = iterable { + let elements = if let Some(iterable) = iterable_opt { iterable.try_to_value(vm)? } else { vec![] }; - // Return empty frozenset singleton for exact frozenset types (when iterable was empty) - if elements.is_empty() && cls.is(vm.ctx.types.frozenset_type) { + // Return empty frozenset singleton + if is_exact_frozenset && elements.is_empty() { return Ok(vm.ctx.empty_frozenset.clone().into()); }